乐趣区

vue自定义通用弹窗组件

弹窗组件咱们很多时候会援用第三方组件,或者写的并不是很通用,只能在独自页面展现,上面咱们来优雅的书写 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 外面,能够在这个文件夹里观看源码

退出移动版