优秀的编程知识分享平台

网站首页 > 技术文章 正文

精通Vue(14):组件状态同步的sync原理

nanyue 2025-10-14 02:13:38 技术文章 1 ℃

sync和v-model有极高的相似度,在第11篇文章中较长的解释了v-model,有兴趣可以翻看看。

这篇我们来解决sync的问题,我觉得它还比较有用,所以写一篇。

先看实例

父组件打开一个modal窗口,但是在关闭时会面临一个很重要的问题,那就是它要不要通知父组件呢?图示如下:

在这里,提出一个名词,称为组件状态的”单一数据源“原则。

单一数据源原则

通俗的说就是,父子组件状态的同步必须遵循”父祖件是状态的所有者“,也就是父祖件控制状态。它的理由大概有两点:

  • 如果子组件自己关闭了,那么父组件的的visible状态还是true,这样状态就混乱了。
  • 父组件中可能还有别的东西依赖父组件的这个状态。比如说,当这个弹窗弹出时,某个按钮要禁用,或者某个组件要不可见等等。也就是说除了父组件,可能还有一堆别的东西也依赖这个状态,所以父组件必须要明确知道当前的状态。

sync使用格式和实现原理

使用方式如下:

<child-modal :visible.sync="isShow"></child-modal>

也比较简单,在绑定的属性名visible后面加一个sync修饰符即可,那么Vue实际生成的我方动作如下:

//伪码
with(this){
  f= function($event){
    isShow = $event
  }
}

可以看到和v-model几乎相同。同时,在子组件的events中创建一个事件,名为:'update:visible',伪码如下:

//伪码
events={
  'update:visible': f
}

名字为:update:xx的样式。

最后,子组件在发生变化时,通过this.$emit('update:visible',value)来调用这个事件,就可以修改父组件的值。状态图示如下:

状态的双向绑定就像一个环。

总结

sync和v-model有99%的相似度,可以参考第11篇的内容。但是可以看出,sync在语境上比v-model更适合父子组件状态的同步,而且主要看它的思想,就是sync主要解决的是什么问题,它在实际开发中使用很广泛。

完整的实验代码

在这个代码中,完整模拟了上面的理论。

<div id="app">
    <!-- 1.依赖isShow的元素 -->
    <h2 v-if="!isShow">我是依赖isShow状态的元素</h2>
    <!-- 2.打开modal -->
    <button @click="isShow = true">打开弹窗</button>
    <!-- 3.弹窗的显隐 -->
    <child-modal :visible.sync="isShow"></child-modal>
</div>
<script src="../vue.js"></script>
<script>
    Vue.component('child-modal', {
        props: ['visible'], // 接收父组件的 visible 属性
        template: `
                <div style="border:1px solid red" v-if="visible">
                    <p>我是弹窗内容</p>
                    <button @click="close">关闭</button>
                </div>
            `,
        methods: {
            close() {
                this.updateVisible(false)
            },
            //封装一个方法
            updateVisible(value){
                this.$emit('update:visible',value)
            }
        }
    });

    new Vue({
        data() {
            return {
                isShow: false // 控制弹窗显示的状态
            }
        }
    }).$mount('#app')
</script>

Tags:

最近发表
标签列表