弹窗组件我们很多时候会引用第三方组件,或者写的并不是很通用,只能在单独页面展示,下面我们来优雅的书写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里面,可以在这个文件夹里观看源码
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。