vue子组件修改父组件的数据
子组件能否修改父组件的数据?
官方文档中提到,vue的设计是单项数据流的模式,官方文档也不建议在子组件中修改props的数据,原因是:这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。,但是实际开发场景中,有一些场景确实碰到了需要在子组件中直接修改props中的数据的情况比如element的dialog,本篇本章记录一下两种在子组件中修改父组件中的数据的方法(注意:不是直接修改子组件中props的数据)
v-model实现父子组件双向数据绑定
众所周知,vue的语法中,可以直接在input,textarea等标签直接绑定v-model事项双向数据绑定,而v-model这个指令本质上就是 :value以及@change方法的二次封装,所以咱们可以利用这个思想,完成父子组件的双向数据绑定
父子组件通信常规写法:
//parentComponent
//$event为默认形参,即change事件带过来的参数,也可写为 @change="(val) => value = val"
<childComponent :value="value" @change="value = $event">
//childComponent
<template>
<div class="hello" @click="change">
{{value}}
</div>
</template>
<script>
export default {
props: ['value'],
methods :{
change() {
this.$emit('change','改变之后的change')
}
}
}
</script>
v-model实现
//parentComponent
//$event为默认形参,即change事件带过来的参数,也可写为 @change="(val) => value = val"
<childComponent v-model="value">
//childComponent
<template>
<div class="hello" @click="change">
{{value}}
</div>
</template>
<script>
export default {
props: ['value'],
model: {
prop: 'value', //这个地方就是上面那种普通写法中的:value的形式 可以取自定义名称,要跟props中的名称同步
event: 'change' //这个地方就是上面那种普通写法中的@change的形式, 可以取自定义名称,内置处理了普通写法中父组件的赋值事件
},
methods :{
change() {
this.$emit('change','改变之后的change')
}
}
}
</script>
v-bind.sync实现双向数据绑定(官方提供)
2.3.0+ 新增 在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以变更父组件,且在父组件和子组件两侧都没有明显的变更来源。
普通写法
//parentComponent
//$event为默认形参,即change事件带过来的参数,也可写为 @change="(val) => value = val"
<childComponent v-bind:title="doc.title" v-on:update:title="doc.title = $event">
//childComponent
<template>
<div class="hello" @click="change">
{{title}}
</div>
</template>
<script>
export default {
props: ['title'],
methods :{
change() {
this.$emit('update:title', newTitle)
}
}
}
</script>
.sync便捷语法
//parentComponent
//$event为默认形参,即change事件带过来的参数,也可写为 @change="(val) => value = val"
<childComponent :title.sync="doc.title">
//childComponent
<template>
<div class="hello" @click="change">
{{title}}
</div>
</template>
<script>
export default {
props: ['title'],
methods :{
change() {
this.$emit('update:title', newTitle)
}
}
}
</script>
注意
- 带有
.sync修饰符的v-bind不能和表达式一起使用 (例如v-bind:title.sync=”doc.title + ‘!’”是无效的)。取而代之的是,你只能提供你想要绑定的 property 名,类似v-model。 - 将
v-bind.sync用在一个字面量的对象上,例如v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。