vue-.sync修饰符的后花园

433 阅读2分钟

繁花似锦

vue的prop是单向下行绑定:父级的prop的更新会向下流动到子组件中,但是反过来不行。可是有些情况,我们需要对prop进行“双向绑定”。这个时候,就可以用.sync来解决。

关于vue.sync的语法糖也很甜.sync是vue中用于实现简单的“双向绑定”的语法糖,在平时的开发中是非常使用的。适用场景也很多,用起来也很给力。

首先看看如果不用.sync的情况下怎么解决prop的双向绑定

子组件:

// info.vue组件定义了一个value 属性, 和一个valueChanged事件
<template>
    <div>
        <input @input="onInput" :value="value"/>
    </div>
</template>

<script>
export default {
    props: {
        value: {
            type: String
        }
    },
    methods: {
        onInput(e) {
            this.$emit("valueChanged", e.target.value)
        }
    }
}
</script>

父组件:

<template>
    <info :value="myValue" @valueChanged="e => myValue = e"></info>
</template>

<script>
    inport info from './info.vue';
    export default {
        components: {
            info,
        },
        data() {
            return {
                myValue: 1234,
            }
        },
    }
</script>

是不是很麻烦,再来看看使用.sync实现prop的双向绑定

父组件:

// index.vue组件
<info :value.sync="myValue"></info>

子组件:

// info.vue组件
...
methods: {
    onInput(e) {
        this.$emit("update:value", e.target.value)
    }
}

具体效果有多好,“码”上可见。

锦上添花

如果一个组件的多个prop都要实现双向绑定,根据上面学到的知识,只需要每个prop加sync修饰符

<info :a.sync="value1" :b.sync="value2" :c.sync="value2" :d.sync="value2"></info>

是不是很麻烦,vue提供了一种更简便的方法, v-bind.sync = “对象”

<info v-bind.sync="obj"></info>
...
<script>
..
data() {
    obj: {a: '', b: '', c: '', d: ''}
}
..
</script>

花开满园

一般在弹出框用的很多,而且十分便捷。

<template>
    <div class="details">
        <myComponent :show.sync='valueChild' style="padding: 30px 20px 30px 5px;border:1px solid #ddd;margin-bottom: 10px;"></myComponent>
        <button @click="changeValue">toggle</button>
    </div>
</template>
<script>
import Vue from 'vue'
Vue.component('myComponent', {
      template: `<div v-if="show">
                    <p>默认初始值是{{show}},所以是显示的</p>
                    <button @click.stop="closeDiv">关闭</button>
                 </div>`,
      props:['show'],
      methods: {
        closeDiv() {
          this.$emit('update:show', false); //触发 input 事件,并传入新值
        }
      }
})
export default{
    data(){
        return{
            valueChild:true,
        }
    },
    methods:{
        changeValue(){
            this.valueChild = !this.valueChild
        }
    }
}
</script>

如果未触发事件 this.$emit('update:show', false); 则外部感知不到子组件内部对show的改变,依然认为此事的值是true,导致弹框点击打开一次之后,后面再不会打开。