子组件接收父组件需要暴露props,但是props是单向流,在子组件中不能更改prop的值,否则报错。在开发过程中会有这种需求,既要接收父组件的传值,又要在子组件改变其值。通常的办法是通过监听子组件的props触发$emit传值给父组件,如下:
子组件:
props: {
//这个是接收父组件的传值
prop1: {
required: true,
type: Number,
default: 1
}
},
//监听,并通知父组件接收
watch: {
//子组件中直接使用prop1
prop1( newValue ) {
//父组件需要通过触发propChange事件接收newValue值
this.$emit( 'propChange', newValue )
}
}
父组件:
<children
@propChange = 'propChange'
/>
methods: {
propChange( value ) {
//这个value就是子组件传过来的值
console.log( value ) ;
}
}
上面的方法相对比较麻烦,父组件需要通过触发事件来获取更新值,如果子组件比较多,方法维护起来比较麻烦(最头疼的是命名 - _ -),vue 2.3.0+ 新增了语法糖 .sync ,可以更便捷的处理父子组件的数据同步。
子组件:
<template>
<div class="">
<div> {{ prop1 }} </div>
<button @click="$emit( 'update:prop1', prop1 +1 )">+1</button>
</div>
</template>
props: {
//这个是接收父组件的传值
prop1: {
required: true,
type: Number,
default: 1
}
}
父组件:
//利用.sync修饰符双向绑定, value就是子组件传来的 prop1 +1
<children :prop1.sync = 'value' />
.sync 是处理prop 双向绑定时比较推荐的方法,但是在 .sync之前的 vue 2.2.0+ 已经增加了一个双向绑定的语法糖 v-model,是的,就是input双向绑定的v-model,这其实也是一个语法糖,只是默认会利用名为 value 的 prop 和名为 input 的事件,所以在使用v-model处理非表单的双向绑定时,尽量避免使用value的prop名和input的事件名,当然也不是不能用,只是尽量避免冲突的可能。下面是v-model的双向绑定例子:
子组件:
<template >
<div> {{ prop1 }} </div>
//这里不能用 prop1++,因为++ 等同于 prop1 = prop1 +1,这就直接改变了prop1的值了,在子组件中是不允许的,传值 prop1 +1给父组件,子组件再接收父组件的值才是正确的逻辑。
<button @click="$emit( 'change', prop1 +1 )"> 加一个 </button>
</template >
//这个model对象是重点, prop:要监听的属性名,event:触发的自定义事件名
model: {
prop: 'prop1',
event: 'change'
},
props: {
prop1: Number
}
父组件:
//这个value 就是子组件传过来的值(prop1 +1)
<ttse v-model="value"/>
data() {
return {
value: 0
}
}