vue自定義通用彈窗組件

彈窗組件咱們不少時候會引用第三方組件,或者寫的並非很通用,只能在單獨頁面展現,下面咱們來優雅的書寫vue的自定義彈窗組件。vue

實現彈窗組件

彈窗這類組件的特色是它們在當前vue實例以外獨立存在,不能寫在當前業務dom內,這樣樣式很差控制,通用性比較差。git

一般掛載於body,經過js動態生成和取消。這裏就說明了一個知識點,要求咱們對實例的建立和實例的掛載有必定的瞭解github

下面咱們來寫個簡單例子。element-ui

create函數
首先咱們要有個明確思路該怎麼作:app

一、建立一個create函數。
二、傳入一個組件的配置(組件顯示自己和它的props參數)。
三、建立它的實例,並將其掛載到body上。
四、最後返回組件實例。
import Vue from 'vue'

// Component爲傳入的組件,props爲傳入的組件參數
export default function create(Component, props) {

  // 建立實例,每一個vue項目的入口文件都會用到就不具體說明了
  // $mount()本質是把虛擬dom轉化爲真實dom,這點很重要
  const vm = new Vue({
    render(h) {
      return h(Component, { props })
    }
  }).$mount()

  // 經過vm.$el獲取生成的dom,把生成的真實dom插入body中
  document.body.appendChild(vm.$el)

  // 獲取根組件實例(這裏不理解能夠去看下前面的文章vue通信大全)
  const comp = vm.$children[0]

  // 彈窗關閉時候調用
  comp.remove = () => {
    // 移除自己
    document.body.removeChild(vm.$el)
    // 釋放本身所佔資源
    vm.$destroy()
  }

  // 返回建立的實例
  return comp
}

看了上面代碼,不少人會問出兩個問題。dom

1.咱們在初始化$mount綁定id爲app的dom節點上,那麼這裏咱們想綁定在body不是能夠直接寫成$mount('body'),這樣就不用在用js去appendChild。
答案是不行,由於官網明確說明了這種方法是覆蓋該dom內全部內容因此不行。可是$mount()本質是把虛擬dom轉化爲真實dom,這點很重要。ide

2.還有些同窗會說出extend方式也能夠建立組件實例並掛載
是的,下面咱們就來實現一下。函數

import Vue from 'vue'

export default function create(Component, props) {
  // vue.extend()獲取建立實例
  const Ctor = Vue.extend(Component)
  // 建立組件實例,這時獲得的是虛擬dom,如何轉化爲真實dom
  const comp = new Ctor({
    propsData: props
  })
  // 前面說到$mount就是這個做用
  comp.$mount()

  // 掛在在body上,這時是comp的dom
  document.body.appendChild(comp.$el)

  comp.remove = () => {
    // 移除自己
    document.body.removeChild(comp.$el)
    // 釋放本身所佔資源
    comp.$destroy()
  }

  return comp
}

這樣寫起來是否是更輕便。ui

傳入的顯示組件

下面簡單寫下傳入顯示組件,也就是上文中的Component參數。這裏就不贅述,比較簡單。this

<template>
  <div v-if="isShow">
    <h3>{{title}}</h3>
    <p>{{message}}</p>
  </div>
</template>

<script>
export default {
// 上文中傳入的props參數
  props: {
    title: {
      type: String,
      default: ""
    },
    message: {
      type: String,
      default: ""
    },
    duration: {
      type: Number,
      default: 1000
    }
  },
  data() {
    return {
      isShow: false
    };
  },
  methods: {
  // 調用show方法展現
    show() {
      this.isShow = true;
      // 使用setTimeout定時關閉
      setTimeout(this.hide, this.duration);
    },
    // 消失後移除自身所佔資源
    hide() {
      this.isShow = false;
      this.remove();
    }
  }
};
</script>

調用彈窗組件

create()返回的是組件自身實例,調用show()方法天然會調用顯示組件裏面methods中的show方法,而後就成功了。

create(Notice, {
  title: '我是自定義彈窗組件',
  message: '我成功出現了',
  duration: 3000
}).show()

以上只是一個簡單的彈窗通用封裝,若是想了解的更深刻能夠參考element-ui的設計理念,去看看其中源碼,相信還會有很多收穫。
地址:https://github.com/ElemeFE/el...
組件都在packages裏面,能夠在這個文件夾裏觀看源碼
image.png

相關文章
相關標籤/搜索