乐趣区

关于javascript:vue-理解sync

之前没怎么了解文档对.sync 的介绍,的确有点菜

思考以下两个父子组件:

// 父组件
{
  template: `
  <div>
      <p>I'm parent</p>
      <p>parentCount: {{parentCount}}</p>
      <child v-bind:childCount="parentCount"></child>
  </div>
  `,
  data() {
      return {parentCount: 1}
  },
}

// 子组件
{
  template: 
  `<div>
    <p>I'm child</p>
    <p>childCount: {{childCount}}</p>
    <button @click="handleClickAdd">add in child</button>
  </div>`,
  props: ['childCount'],
}

父组件将值 parentCount 作为 propchildCount传给子组件,咱们心愿点击子组件中按钮,使得父组件中的 parentCount 和子组件中的 childCount 都 +1,咱们想当然地这么写:

  // 子组件
  methods: {handleClickAdd() {
      // 只需在子组件中对 childCount+1,作为数据源,parentCount 也会 +1
      this.childCount += 1
    }
  }

尝试点击按钮,会发现父组件的数据没有变动:

同时控制台正告:

vue.js:634 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated:"childCount"

found in

---> <Child>
       <Root>

这就是所谓的单向数据流

父级 prop 的更新会向下流动到子组件中,然而反过来则不行

想当然的方法果然行不通。换个思路:既然 prop 的流动是单向的,咱们能够在子组件中抛出事件,来告诉父组件更新 parentCount,这样 childCount 天然也更新了。别忘了,事件名不存在任何自动化的大小写转换,因而咱们能够抛出叫做 update:childCount 的事件——父组件,你传进来的 propchildCount更新了!父组件侦听到该事件后,把更新后的值赋给 prop 对应的数据源 parentCount 就行了:

  // 子组件
  methods: {handleClickAdd() {this.$emit('update:childCount', this.childCount + 1)
    }
  }

// 父组件
`
<child 
  v-bind:childCount="parentCount" 
  v-on:update:childCount="parentCount=$event">
</child>
`

当初的代码就满足咱们的需要了:

咱们回过头来看,父组件这么写多少有些轻便——差不多把 childCount=parentCount 写了两遍。因而,vue 提供了.sync 缩写:绑定 prop 时加上.sync,vue 就会主动为咱们设置叫做 update:propName 的更新事件。因而,下面的父组件代码齐全等价于:

`
<child 
  v-bind:childCount.sync="parentCount">
</child>
`

有趣味的话,还能够到源码里确认一下:

退出移动版