1.项目中遇到的问题
在项目中,碰到父组件向子组件传一个对象数据,子组件修改props里接受父组件的数据, 父组件的数据也
发生变化的问题,具体的代码如下
Parent.vue
<template>
<div>
<child :infor="infor" :inforLabel="inforLabel"></child>
</div>
</template>
<script>
import child from "./Child.vue";
export default {
components: { child },
data() {
return {
infor: {
grade: "",
},
inforLabel: {
model: "grade",
},
};
},
};
</script>
//Child.vue
<template>
<div>
成绩<input type="text" v-model="infor[inforLabel.model]">
</div>
</template>
<script>
export default {
props: {
infor:Object,
inforLabel:Object,
},
}
</script>
2.具体遇到的情况就是这个输入框输入数据,父组件的属性也会发生变化。打开vue-dev-tool,可以很清楚地看到父组件随input输入而变化。
3.原因
在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,
在子组件内部改变它会影响父组件的状态。因此如果需要父子组件的双向数据绑定,可以利用这一特性,
如果父组件单向向下绑定,则可以传递简单类型,或者进行深拷贝,复制一份与父组件的数据相同,
但地址不同的独立属性
4.解决方案
4.1利用 assign,上面的代码可以改成这个样子
Parent.vue
<template>
<div>
成绩<input type="text" v-model="inforObj[inforLabelObj.model]">
</div>
</template>
<script>
export default {
props: {
infor:Object,
inforLabel:Object,
},
data(){
return {
inforObj:{},
inforLabelObj:{}
}
},
watch: {
//当子组件监听到props里的属性发生变化,则进行数据拷贝
infor:{
handler(val,oldval){
//assign只能进行浅拷贝{a:'b'}这样的,不能拷贝引用类型像{a:{b:'c'}}这样的
this.inforObj= Object.assign({},infor);
},
//别忘记开启深度监听
deep:true
},
inforLabelObj:{
handler(val,oldval){
//assign只能进行浅拷贝{a:'b'}这样的,不能拷贝引用类型像{a:{b:'c'}}这样的
this.inforLabelObj= Object.assign({},infor);
},
deep:true
}
}
}
</script>
效果
4.2利用JSON
Child.vue
<template>
<div>
成绩<input type="text" v-model="inforObj[inforLabelObj.model]">
</div>
</template>
<script>
export default {
props: {
infor:Object,
inforLabel:Object,
},
data(){
return {
inforObj:{},
inforLabelObj:{}
}
},
watch: {
//当子组件监听到props里的属性发生变化,则进行数据拷贝
infor:{
handler(val,oldval){
this.inforObj=JSON.parse(JSON.stringify(val))
},
//别忘记开启深度监听
deep:true
},
inforLabelObj:{
handler(val,oldval){
this.inforLabelObj=JSON.parse(JSON.stringify(val))
},
deep:true
}
}
}
</script>