组件内开发这样开发有一点优势,Form组件与其父组件之间可以通过prop以及$emit方便通信。但是也会有以下几个缺陷:
- 当前组件的data必须要有UI.isOpen来控制表单,如果存在多个表单时,就会有大量的状态来维护表单的开关;
- 如果表单多次弹出时,可能需要对表单的data进行重置;
- 与组件化思想相违背,表单不属于当前页面,它只是由于用户行为触发的结果。
为了解决以上缺陷,并且还能具备方便通信的优势,本文选择用Vue.extend将原有
组件的子类const _constructor = Vue.extend(component)
然后return function,它的功能是:
- 将组件转化为method
- 在method调用时,将组件实例化并传递propsData
const {
propsData
} = options
let instance = new _constructor({
propsData
}).$mount(document.createElement('div'))
为了能够控制实例化后的组件,选择instance返回。
当组件实例化时,它只是挂载到document.createElement('div')上,但是并没有挂载到页面上,所以需要将其appendChild到页面中。为了更好的语义化,选择在组件的生命周期中完成它在页面中的挂载。实例化时,会触发组件mounted生命周期,所以当其触发时可以挂载在document.body中,具体如下
mounted () {
document.body.appendChild(this.$el)
}
有了挂载,就必须要有注销。对应的生命周期应该是destroyed,所以
method: {
destroyElement () {
this.$destroy()
}
},
destroyed () {
this.$el.parentNode.removeChild(this.$el)
}
组件注销的时间与它在页面中显示息息相关,当
在页面中不可见时候,需要注销它method: {
destroyElement () {
this.$destroy()
}
},
destroyed () {
this.$el.parentNode.removeChild(this.$el)
}
一般Form组件有两个功能:
- done:代表用户确认;
- cancel:代表用户取消;
当done或cancel触发时,APP组件内可能会有相应的变化,所以在组件实例化之后,利用$on去监听对应的done事件以及cancel事件。
done && inlineListen({
method: 'done',
options,
instance
})
cancel && inlineListen({
method: 'cancel',
options,
instance
})
其中inlineListen函数可以方便后续添加其他的event,其代码为
const inlineListen = ({
method,
options,
instance
}) => {
let listener = `on${method}`
instance[listener] = options[method]
instance.$on(method, function (data) {
this[listener](data)
})
}
也可以将上述方案封装成Promise形式,如下
export const transform = (component) => {
const _constructor = Vue.extend(component)
return function (options = {}) {
const {
propsData
} = options
return new Promise((resolve, reject) => {
let instance = new _constructor({
propsData
}).$mount(document.createElement('div'))
instance.$on('done', data => resolve(data))
})
}
}
使用
可以将上述属于
公有的data以及method独立出来,再通过mixins引入到每个表单内,例如export default {
data() {
return {
visible: true
}
},
watch: {
visible(newValue) {
if (!newValue) {
this.destroyElement()
}
}
},
mounted() {
document.body.appendChild(this.$el)
},
destroyed() {
this.$el.parentNode.removeChild(this.$el)
},
methods: {
destroyElement() {
this.$destroy()
},
close() {
this.visible = false
}
}
}
再通过mixins混入。
调用时,只需
export default {
name: 'App',
methods: {
register: transform(register),
handleClick () {
this.register({
propsData: {
...
},
// done: data => function
done () {
// 外部关闭
this.close()
}
})
}
}
}
PS:如果业务场景需要,在外部控制表单的关闭时,只需要改变done function的context,也就是this指针指向
。总结
通过上述的transform函数,将原有的注入式组件转化为了命令式,简化了页面状态的维护,在通过mixins混入公有data以及method,简化了表单组件开发。上述方法也可用于开发toast、alert、confirm等组件,只需要将
Vue.prototype.method = transform(Toast-Component)
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对创新互联的支持。
名称栏目:利用Vue构造器创建Form组件的通用解决方法
网站路径:http://shouzuofang.com/article/geigge.html