官网解释
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
示例
我们通过一个示例来解释单向数据流与双向绑定,这个示例是对ant-design-vue表单组件的二次封装
a-input原始用法
<template>
<a-input v-model='data'/>
</template>
<script>
export default {
data() {
return {
data: ''
}
}
}
</script>
在data
中声明的属性会通过Object.definePropty
方法为其添加get
和set
方法,使其成为响应式数据。v-model
是一个语法糖,在vue
2.2.0
版本后新增了model属性
官方解释
允许一个自定义组件在使用
v-model
时定制 prop 和 event。默认情况下,一个组件上的v-model
会把value
用作 prop 且把input
用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用value
prop 来达到不同的目的。使用model
选项可以回避这些情况产生的冲突。
我们利用这个属性来对上述input
组件做二次封装
组件代码
<template>
<a-input :value='currentValue' @change='onInputChange'/>
</template>
<script>
export default {
data() {
return {
currentValue: this.value
}
},
model: {
event: 'change',
prop: 'value'
},
props:{
value: {
type: String
}
},
watch: {
value: {
handler(newVal) {
this.currentValue = newVal
}
}
},
onInputChange(e) {
this.$emit('change', e.target.value)
}
}
</script>
在父组件中使用
<template>
<my-input v-model='data' />
</template>
<script>
export default {
data() {
return {
data:''
}
}
}
</script>
上述子组件中的currentValue
是实际input
组件的值,他的值是根据父组件传入的值得出的,input
标签组件的change
事件来触发父组件的change
事件,从而改变传入子组件props
中value
的值。这就解释了单项数据流,父組件通过props
向子组件传递值,子组件通过emit
事件来通知父组件修改值,子组件不在自身对父组件传递过来的props
做任何修改,都是通过父组件来更新props
,从而达到子组件更新自身状态。
使用场景
当我们在实现一个由数据渲染的复杂表单时,那么我们的设计就可以采用这种模式,通过props
以及emit
传递,保证子组件的事件触发根节点的数据更新,从而更新子孙组件的状态。