在理解vue为什么是单向数据流之前,简单复习下prop,
prop也就是父组件传过来的数据,如果我们试图通过子组件的v-model去改变这个prop,也就是试图通过子组件直接去改变父组件的数据,而不是通过发送事件的方式,这是不允许的。
这是因为vue是单向数据流
也就是说,数据总是从父组件传到子组件,子组件没有权利修改父组件传过来的数据,只能请求父组件对原始数据的修改。
这实际上是为了更好的解耦,在开发中如果有多个子组件依赖与父组件的某个数据,万一子组件真的可以直接修改父组件的数据,那么一个子组件的变化将会引发所有依赖于这个数据的子组件的变化,所以vue不推荐子组件直接修改父组件的数据,直接修改prop会抛出警告。
如果我们真的确实需要操作这个数据,该怎么办呢?
有两种方法:
1.定义一个局部变量,并用prop的值初始化它
props:['initialCounter'],
data:function() {
return {
counter:this.initialCounter
}
}
2.定义一个计算属性,处理prop并且返回
props:['size'],
data:function() {
addsize:function() {
return this.size.trim().toLowerCase()
}
}
这里还需要注意一个问题:
比如下面这段代码:
<div id="app">
<h3>父组件的数据:{{parent}}</h3>
<cpn :obj1="parent"></cpn>
</div>
<template id="cpn">
<div>
<h2>子组件的数据:{{son}}</h2>
<input type="text" v-model="son.age">
</div>
</template>
const cpn = {
template:"#cpn",
props:["obj1"],
data() {
return {
son:this.obj1
}
}
}
const app = new Vue({
el:"#app",
data:{
parent: {
age:18
}
},
components:{
cpn
}
})
这里的this.obj1是引用,赋值给了son,所以son实际还是指向了父组件的数据,对son.age的修改会影响到父组件。
所以,我们需要的是一个对象的副本,因为对象都是基本类型,这里只用浅拷贝就可以(如果对象属性还是对象,就用深拷贝)
const cpn = {
template:"#cpn",
props:["obj1"],
data() {
return {
son:Object.assign({},this.obj1)
}
}
}
之后会发现,子组件的数据操作不会影响到父组件