五分钟彻底明白Vue .sync修饰符

2,069 阅读2分钟

大家先一起看一下官方解释


可以看出.sync的目的是实现双向绑定(这里的双向绑定指的是子组件共享父组件的数据,父组件的数据改变子组件的数据会跟着一起改变,子组件也能改变父组件的数据)

自己实现双向绑定

父组件

<template>
  <div>
    <div>parent:{{msg}}</div>
    //自定义一个handleMsg事件,子组件通过$emit调用
    <Child :msg="msg" @handleMsg="changeMsg"></Child>
    <button @click="changeMsg">父组件按钮</button>
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  data(){
    return {
      msg : 'hello'
    }
  },
  components: {
    Child
  },
  methods: {
    changeMsg(){
      this.msg = Date.now().toString();
    }
  },
}
</script>

子组件

<template>
  <div>
    child:{{msg}}
    <button @click="$emit('handleMsg')">子组件按钮</button>
  </div>
</template>

<script>
export default {
  props: {
    msg: String
  }
};
</script>

效果展示

.sync修饰符的实现(传单个值)

其实.sync修饰就是对上面代码的简写,但是有一些额外的限制与局限;

父组件

<template>
  <div>
    <div>parent:{{msg}}</div>
    //对父级的msg绑定sync修饰符,不需要在绑定额外的事件
    <Child :msg.sync="msg"></Child>
    <button @click="changeMsg">父组件按钮</button>
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  data(){
    return {
      msg : 'hello'
    }
  },
  components: {
    Child
  },
  methods: {
    changeMsg(){
      this.msg = Date.now().toString();
    }
  },
}
</script>

子组件

<template>
  <div>
    child:{{msg}}
    // 此处$emit调用的事件'update:msg'是内部实现好的,这里update是写死的,必须是update,
    // msg是父组件sync修饰符绑定的变量,'666'是赋给父组件sync修饰符绑定的变量
    // 由于用法是写死的,所以sync修饰符常被用来改变父组件的boolean类型的变量
    <button @click="$emit('update:msg','666')">子组件按钮</button>
  </div>
</template>

<script>
export default {
//如果js内部不使用父组件传过来的msg,这里可以不用props接收,程序仍能正常运行
  props: {
    msg: String
  }
};
</script>

效果展示

虽然通过.sync修饰符我们很简单的实现了与上面一样的功能,但是.sync只能做一些简单的事,过于复杂的功能他就帮不上什么忙了

.sync修饰符的实现(传多个值)

父组件

<template>
  <div>
    <Slider v-bind.sync="doc"></Slider>
    <div>{{this.doc.x}}</div>
    <div>{{this.doc.y}}</div>
  </div>
</template>

<script>
import Child from './Child.vue'

export default {
  data(){
    return {
      doc:{
        x:0,
        y:100
      }
    }
  },
  components: {
    Child
  },
}
</script>

子组件

<template>
  <div class="slider">
    <div @click="$emit('update:x',2)">slider111</div>
    <div @click="$emit('update:y',20)">slider222</div>
  </div>
</template>

通过这种方式,我们把doc对象中的每一个属性都作为一个独立的prop传进去,然后各自添加用于更新的v-on监听器

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