手写Vue弹窗Modal的实现代码(3)

'use strict' import Confirm from './Confirm.vue' const confirmConstructor = Vue.extend(Confirm) const ConfirmViewStyle = config => { const confirmInstance = new confirmConstructor({ data() { return { config } } }) confirmInstance.vm = confirmInstance.$mount() confirmInstance.dom = confirmInstance.vm.$el document.body.appendChild(confirmInstance.dom) } const close = () => { let dom = document.querySelector('body .modelServe-container') dom && dom.remove() Vue.prototype.$receive = null } const closeConfirm = () => { let dom = document.getElementById('__confirm') dom && dom.remove() Vue.prototype.$confirm = null } function install(Vue) { Vue.prototype.modelServe = { confirm: (obj) => { return new Promise(resolve => { Vue.prototype.$confirm = (data) => { resolve(data) closeConfirm() } ConfirmViewStyle(obj) }) } } Vue.prototype.$dismiss = close Vue.prototype.$cancel = closeConfirm } Vue.use(install) export default install

思路很简单,在我们创建的时候同时返回一个promise,同时将resolve通行证暴露给vue的一个全局方法也就是将控制权暴露给外部,这样我们就可以向这样,我上面的confiram.vue是直接把取消绑定成了$cancel,把确定绑定成了$confirm,所以点击确定会进入full,也就是.then中,当然你也可以传参数

this.modelServe.confirm({ msg: '返回后数据不会被保存,确认?', ifBtn: true }).then(_ => { this.goBack() }).catch()

写的有点多,其实还可以扩展出好多技巧,比如模态框中传一个完整的组件,并展示出来,简单地写一下,其实只需改动一点

import Model from './Model.vue' const modelConstructor = Vue.extend(Model) const modelViewStyle = (obj) => { let component = obj.component const modelViewInstance = new modelConstructor({ data() { return { disabledClick: obj.stopClick // 是否禁止点击遮罩层关闭 } } }) let app = document.getElementById('container') modelViewInstance.vm = modelViewInstance.$mount() modelViewInstance.dom = modelViewInstance.vm.$el app.appendChild(modelViewInstance.dom) new Vue({ el: '#__model__', mixins: [component], data() { return { serveObj: obj.obj } } }) } ... Vue.prototype.modelServe = { open: (obj) => { return new Promise(resolve => { modelViewStyle(obj, resolve) Vue.prototype.$receive = (data) => { resolve(data) close() } }) } }

调用:

sendCallBack() { this.modelServe.open({ component: AddCallback, stopClick: true }).then(data => if (data === 1) { this.addInit() } else { this.goBack() } })

这里我们用了mixins,最后最后再简单地介绍一下mixins,extend,extends的区别

**- Vue.extend使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

mixins 选项接受一个混入对象的数组。这些混入实例对象可以像正常的实例对象一样包含选项,他们将在 Vue.extend() 里最终选择使用相同的选项合并逻辑合并。举例:如果你的混入包含一个钩子而创建组件本身也有一个,两个函数将被调用。Mixin 钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。

注意(data混入组件数据优先钩子函数将混合为一个数组,混入对象的钩子将在组件自身钩子之前调用,值为对象的选项,例如 methods, components 和 directives,将被混合为同一个对象。两个对象键名冲突时,取组件对象的键值对。)

extends 允许声明扩展另一个组件(可以是一个简单的选项对象或构造函数),而无需使用 Vue.extend。这主要是为了便于扩展单文件组件。这和 mixins 类似。**

概括

extend用于创建vue实例 mixins可以混入多个mixin,extends只能继承一个 mixins类似于面向切面的编程(AOP),extends类似于面向对象的编程 优先级Vue.extend>extends>mixins

总结

到这里,关于如何实现通过方法调用一个Vue组件内容以及用到的一些API以及原理就差不多了,代码如有不懂得地方可以随时提问,欢迎交流。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/a21f3dd42e19278b8182c0a29683685c.html