在vue2当中,全局组件比如弹窗组件如何封装呢?
有些小伙伴可能就简单的封装一个,这种功能也是很完备的
缺点:需要引入额外响应式变量,方法去控制
优点:像el-dialog一样,适合需要定制性更大的场景
那么对于定制性要求更小的场景,因此适合展示较为简单的内容,ElementUI是推荐: messageBox
组件,
看下它的用法:
这种类似于原生alert弹窗
的,就是函数式调用
,那么如何封装一个这样的组件呢? 下面会一一道来
this.$alert
?这个官方给出了答案
就是利用原型链
Vue.prototype.$alert = function(message, title, options){
// 这里写逻辑
}
$alert
当中怎么将弹窗组件创建出来?看一下脚手架的工程文件,main.js
import Vue from "vue"
import App from "./App.vue"
const vm = new Vue({
render: (h) => h(App),
});
vm.$mount("#app")
这里的过程其实就是,
h函数
是一个用来创建 vNode 的辅助函数。能将引入的APP组件
,变成vNode
$mount
)到#app
这个真实dom当中其实$alert
里面做的事情无非就是这样嘛,将我们的.vue组件,挂载到真实dom下
可以看到el的MessageBox 是挂在body下的
回到之前开头实现Modal,分别3个属性,2个自定义事件
内部方法构成:
前面提到了,只需要构造一个用于创建和挂载的函数,然后挂载到Vue.prototype即可全局调用
现在的目标就是构造这样一个函数
新建一个index.js,
import Vue form 'vue'
import Modal from "./Modal.vue"
export default function $modal (){
const vm = new Vue({
render:(h) => h(Modal)
})
// 创建游离节点
const div = document.createElement('div')
// 放到body上
document.body.appendChild(div)
// 将vm挂载到这个节点上
vm.$mount(div)
}
打印一下这个vm
可以看到$el这一项是一个注释节点,因为我们设计的是v-if,此时没命中,因此会创建一个注释节点。
此时我们需要将showModal等参数传进去,该怎么办呢?
h函数就派上用场了,它的第2个参数可以传一些配置项
(就是.vue
里面的配置项)进去
h(Modal,{props:{showModal:true}})
这样子就有渲染Modal了,但这个h函数的第2个参数只能传入包含模板相关属性(例如 props
、class
、style
等),如果要传入方法的话,只能另寻他法了
所幸Vue提供了Vue.extend
从官方文档可以看到,extend需要传入一个配置项
,但我们Modal.vue
组件已经写好了呀,总不能重新写一份到template
,或者写一个render
函数吧?
知道你很急,但你先别急,此时你就要知道.vue文件
,被import引入
之后是什么?
.vue组件
究竟是啥???在 import Modal from './Modal.vue'
之后, 打印一下Modal
这不就是一个对象,这熟悉的属性名,不就options配置项
嘛
回忆一下.vue当中,是怎么写代码的
同时vue的编译器帮我们把标签
里的内容编译成了render函数
啦
所以就可以利用vue.extend进行改造啦,extend当中的配置项会以优先级更高的形式混入
import Vue form 'vue'
import Modal from "./Modal.vue"
export default function $modal (){
const ModalCtor = Vue.extend(Modal)
const modalVM = new ModalCtor({
propsData: {
showModal: true,
title: "JetTsang's Title",
text:"这是text"
},
data() {
return { }
},
mounted(){
console.log('mounted了')
},
methods:{
传入的方法(){
console.log('Hello JetTsang')
}
}
})
const div = document.createElement('div')
document.body.appendChild(div)
modalVM.$mount(div)
}
打印一下这个modalVM
,这就是1个vue组件了啊,可以通过写配置项来传入方法和属性了.
可以借助下面的流程
最后 $modal(message, title, options)
的参数设计,相信难不倒各位
这里是有promise的调用形式啊
其实就是在index.js
暴露的$modal
函数当中返回一个promise嘛,我们直接用promise包装一下即可:
import Vue form 'vue'
import Modal from "./Modal.vue"
export default function $modal (){
const ModalCtor = Vue.extend(Modal)
// 返回1个promise实例
return new Promise((resolve,reject)=>{
const modalVM = new ModalCtor({
methods:{
// 确认
_confirm(){
// 在这里调用
resolve()
console.log('Hello JetTsang')
}
}
})
const div = document.createElement('div')
document.body.appendChild(div)
modalVM.$mount(div)
})
}
当然这里面方法也是多种多样,相信诸君一定比我想的好。
这种函数式全局组件的封装,需要考虑将组件挂载和卸载的过程,比较考验对vue组件本质的理解
当然要想实现一个好用的函数式组件,还需要考虑单例、层级z-index,初始生成位置等等