之前没怎么了解文档对.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>`
有趣味的话,还能够到源码里确认一下: