弹窗类组件的特点
弹窗类组件的特点就是他们在当前的vue实例之外独立存在,通常挂载于body。他们是通过纯JS创建的,不需要在任何组件中声明。常见的食用方式是这样:
this.$create(Notice, {
title: '标题标题',
message: '提示信息'
}).show();
分析实现思路
根据上面的实用方式,我们要想实现在vue组件中全局使用this.$create()方法,就需要将该方法赋值到vue的原型对象上。假设我们已经实现了create方法:
Vue.prototype.$create = create
分析下create函数,它接受两个参数,一个是组件配置对象,命名为Component,一个是参数属性,我们将他命名为props。要想将该组件配置对象挂载到body上,就需要构建Component实例,这样才能生成真实的dom节点。顺着这个思路,拿到真实的dom元素后,将该元素append到body上。再给其添加个remove方法,在移除的时候删除节点销毁自身,就大功告成了。
实现方式
借鸡生蛋式——借助Vue构造函数
在vue项目的main.js中,我们要想在body上挂载app组件,是这样写的:
new Vue({
render: h => h(App)
}).$mount('#app')
这里的h就是createElement,它可以返回一个vnode即虚拟dom。$mount方法则可以将render函数中返回的vnode转化为真实节点,并挂载到目标元素上。需要注意一点:
$mount()是覆盖性操作。
所以我们在实现create时,不能够直接使用$mount(body),将真实节点挂载到body上。但是可以不设置挂载目标,这样依然可以转换vnode为真实节点。
所以我们也可以借助这种方式:
import Vue from 'vue'
export default function create (Component, props) {
// 1. 构建Component的实例
const vm = new Vue({
render: (h) => {
return h(Component, {
props})
}
// 不能直接挂载在body节点上,因为$mount()是