弹窗组件咱们很多时候会援用第三方组件,或者写的并不是很通用,只能在独自页面展现,上面咱们来优雅的书写vue的自定义弹窗组件。

实现弹窗组件

弹窗这类组件的特点是它们在以后vue实例之外独立存在,不能写在以后业务dom内,这样款式不好管制,通用性比拟差。

通常挂载于body,通过js动静生成和勾销。这里就阐明了一个知识点,要求咱们对实例的创立和实例的挂载有肯定的理解

上面咱们来写个简略例子。

create函数
首先咱们要有个明确思路该怎么做:

1、创立一个create函数。
2、传入一个组件的配置(组件显示自身和它的props参数)。
3、创立它的实例,并将其挂载到body上。
4、最初返回组件实例。
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}

看了下面代码,很多人会问出两个问题。

1.咱们在初始化$mount绑定id为app的dom节点上,那么这里咱们想绑定在body不是能够间接写成$mount('body'),这样就不必在用js去appendChild。
答案是不行,因为官网明确阐明了这种办法是笼罩该dom内所有内容所以不行。然而$mount()实质是把虚构dom转化为实在dom,这点很重要。

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}

这样写起来是不是更轻便。

传入的显示组件

上面简略写下传入显示组件,也就是上文中的Component参数。这里就不赘述,比较简单。

<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外面,能够在这个文件夹里观看源码