最近在封装一个弹窗组件时,用了比较复杂的逻辑去做显示和隐藏的逻辑,在查看同事的代码之后,才知道还有更简单的方法,自己已经忘了一些API.
popup组件里统一的template:
<div v-if='isShowPopup'>
// 弹窗内容
</div>
自己的方法:
data(){return {isShowPopup: false,}},methods: {showPopup() {this.isShowPopup = true},closePopup() {this.isShowPopup = false}}
在外部通过给popup组件绑定ref=‘xxx’,从而通过this.$refs.xxx.showPopup()/ closePopup() 实现显示和隐藏控制
同事的方法:
// popup组件 props: {show: {type: Boolean,default: true},},computed: {isShowPopup: {get() {return this.show;},set(val) {this.$emit("update:show", val);}}},
在外部通过给popup组件绑定:show.sync=‘xxx’,从而通过this.xxx = true / false 实现显示和隐藏控制
从以上可以看到,同事的方法实现思路更加清晰,也比较符合官方文档的要求:
以上的意思总结:在某些情况下,我们可能需要对组件的一个prop值进行“双向绑定”。真正的双向绑定可能会产生维护问题,因为该变化的来源在父组件和子组件中都不明显。所以我们建议在子组件里以update:myPropName的模式发出事件,父组件可以以:myPropName.sync=‘xxxx’ 绑定在子组件里。
代码比较如下:
传统的方法
<text-document:title="doc.title"@updateTitle="doc.title = $event"
></text-document>
在text-document的子组件里以 this.$emit(“updateTitle”, xxx);发出
新的方法:
<text-documentv-bind:title="doc.title"v-on:update:title="doc.title = $event"
></text-document>
可简写成
<text-document v-bind:title.sync="doc.title"></text-document>
在text-document的子组件里以 this.$emit(“update:title”, xxx);发出
可以看到在新的方法里,用户可通过.sync 和 update: 就可知道父子之间的传值关系
喜欢思考的小伙伴的,可能发现v-model不也是双向绑定吗,是不是里面也是.sync 和 update: 的一种实现?
没错!
<ChildComponent v-model="pageTitle" />// would be shorthand for<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
所以也可以写成:
<ChildComponent v-bind:value.sync="pageTitle" />
v-model默认是使用value作为prop,input作为事件,如果想改的话,可以借助于model,
Vue.component('base-checkbox', {model: {prop: 'checked',event: 'change'},props: {checked: Boolean},template: `<inputtype="checkbox"v-bind:checked="checked"v-on:change="$emit('change', $event.target.checked)">`
})
需要注意的是,你仍然需要在组件的props选项中声明 checked
更多细节可参考官方文档:https://v2.vuejs.org/v2/guide/components-custom-events#sync-Modifier