Skip to content
本页目录

复习之用v-bind 指令的修饰符.sync实现双向数据绑定 - 知乎

除了使用 v-model 指令实现组件与外部数据的双向绑定外,我们还可以用 v-bind 指令的修饰符 .sync 来实现。

那么,该如何实现呢?

先回忆一下,不利用 v-model 指令来实现组件的双向数据绑定:

html
    <div id="app">
        <!-- 双向数据绑定,手动绑定 -->
        <base-input
        :value="name"
        @input="name = $event"
        >
    </div>

    <script>
        Vue.component('base-input', {
            props: {
                value: String
            },
            template: `
            <label>
                姓名:
                <input type="text" :value="value" 
                @input="$emit('input', $event.target.value)"/>
            </label>
            `
        })
        const vm = new Vue({
            el: "#app",
            data: {
                name: 'hello'
            }
        })
    </script>

那么,我们也可以试着,将监听的事件名进行更改,如:

html
    <div id="app">
        <!-- 双向数据绑定,手动绑定 -->
        <base-input
        :value="name"
        @update:value="name = $event"
        >
    </div>

    <script>
        Vue.component('base-input', {
            props: {
                value: String
            },
            template: `
            <label>
                姓名:
                <input type="text" :value="value" 
                @input="$emit('update:value', $event.target.value)"/>
            </label>
            `
        })
        const vm = new Vue({
            el: "#app",
            data: {
                name: 'hello'
            }
        })
    </script>

这样也是可以实现双向数据绑定的。

那么和 .sync 修饰符 有什么关系呢?

此时,我们对代码进行修改:

html
    <div id="app">
        <!-- 双向数据绑定,手动绑定 -->
        <base-input
        :value.sync="name"
        >
    </div>

    <script>
        Vue.component('base-input', {
            props: {
                value: String
            },
            template: `
            <label>
                姓名:
                <input type="text" :value="value" 
                @input="$emit('update:value', $event.target.value)"/>
            </label>
            `
        })
        const vm = new Vue({
            el: "#app",
            data: {
                name: 'hello'
            }
        })
    </script>

所以,.sync 修饰符 本质上也是一个语法糖,在组件上使用:

html
<base-input :value.sync="name"></base-input>

等价于:

html
<base-input
  :value="name"
  @update:value="name = $event"
/>

当我们用一个对象同时设置多个prop时,也可以将.sync修饰符和 v-bind配合使用:

html
<base-input v-bind.sync="obj"></base-input>

注意:

带有.sync修饰符的v-bind指令,只能提供想要绑定的属性名,****不能****和表达式一起使用,如:``:title.sync="1+1"``,这样操作是无效的。

将 ``v-bind.sync`` 用在 一个字面量对象上,如 ``v-bind.sync="{ title: 'haha' }"``,是无法工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。

v-model 与 .sync 的区别?

先明确一件事情,在 vue 1.x 时,就已经支持 .sync 语法,但是此时的 .sync 可以完全在子组件中修改父组件的状态,造成整个状态的变换很难追溯,所以官方在2.0时移除了这个特性。然后在 vue2.3时,.sync又回归了,跟以往不同的是,现在的.sync完完全全就是一个语法糖的作用,跟v-model的实现原理是一样的,也不容易破环院有的数据模型,所以使用上更安全也更方便。

  • 两者都是用于实现双向数据传递的,实现方式都是语法糖,最终通过 ``prop`` + ``事件`` 来达成目的。
  • vue 1.x 的 .sync 和 v-model 是完全两个东西,vue 2.3 之后可以理解为一类特性,使用场景略微有区别。
  • 当一个组件对外只暴露一个受控的状态,并且都符合统一标准的时候,我们会使用v-model来处理。.sync则更为灵活,凡是需要双向数据传递时,都可以去使用。