本文是个人对vue响应式的理解,如果有错误欢迎大家指正
阅读本文前请大家仔细理解官网中的响应式内容
https://cn.vuejs.org/v2/guide/reactivity.html
响应式,官网的说法是:当你把一个普通的 JavaScript 对象传给 Vue 实例的 data
选项,Vue 将遍历此对象所有的属性,并追踪等。。。
我个人总结的是:未响应过的数据在第一次放到data选项中会被遍历然后进行追踪,给已经追踪过的数据添加新的属性如果不按照官网说的方式,则新加的属性不会被追踪
响应的时候只要有一个被响应的属性值改变就会重载一次数据,请看vue生命周期图 下图(when data changes)
下面粘出我的测试代码
在Child文件中
<template>
<div @click="testParentClick" style="background: red;width: 100%;height: 100px"></div>
</template>
<script>
export default {
name: "Child",
// data之所以用方法的方式,也是由于响应式,用有个function能保证每次创建的对象都是一个新的,如果不用function的形式就会出现(A,B都在调用该组件)在父类A中改变该组件的值,那么父类B中也会被改变,这是我个人理解;官方:https://cn.vuejs.org/v2/guide/components.html#data-%E5%BF%85%E9%A1%BB%E6%98%AF%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0
data(){
return {
childData:[]
}
},
methods:{
testChildClick(){
// 创建一个测试数据
let testData=[
{name:'王二',age:'12'},
{name:'张三',age:'13'},
{name:'李四',age:'14'},
];
console.log('子组件test1')
console.log(testData) // 可以在控制台查看该对象是不是被响应了,结果:未被响应(测试该项的时候请先不要传值给父类要分步测试,如果传给父类了也会被改变)
// 将数据传给父组件
// this.$emit('parent-no-respond',testData) // 测试父类时使用
// 将 testData 给 childData,这是第一次赋值,会被响应
this.childData=testData
console.log(this.childData) // 响应数据
console.log('子组件test2')
console.log(testData) // 发现此时数据是响应的了
// 将数据传给父组件
// this.$emit('parent-respond',testData) // 测试父类时使用
},
testParentClick(){
// 创建一个测试数据
let testData=[
{name:'王二',age:'12'},
{name:'张三',age:'13'},
{name:'李四',age:'14'},
];
// 将数据传给父组件
this.$emit('parent-no-respond',testData) // 测试父类时使用
// 将 testData 给 childData,这是第一次赋值,会被响应
this.childData=testData
// 将数据传给父组件
this.$emit('parent-respond',testData) // 测试父类时使用
}
}
}
</script>
<style scoped>
</style>
在父组件中Parent文件
<template>
<child @parent-no-respond="noRespond" @parent-respond="respond"></child>
</template>
<script>
import Child from "./Child";
export default {
name: "Parent",
components: {Child},
data(){
return {
noRespondData:null,
respondData:null
}
},
methods:{
noRespond(noData){
console.log('父组件noRespond')
console.log(noData)// 此时发现数据是未响应的
this.noRespondData=noData
console.log(noData)// 此时发现数据是响应的,因为noData一开始是未响应的,第一次赋值给data中的noRespondData会走getter setter 遍历属性
},
respond(respondData){
console.log('父组件respond')
console.log(respondData)// 此时发现数据是响应的
// 给数据中每个人添加一个sex
respondData.forEach((item)=>{
if (!('sex' in item)) {
item['sex'] = 11
}
})
console.log(respondData)// 此时发现sex是不响应的
this.respondData=respondData
console.log(this.respondData)// 此时发现sex是不响应的
/*之所以是sex是不响应的,因为respondData是已经被响应的不会再走官网说的getter和setter,所以新增的属性不会再响应。
如果想要sex响应
item['sex'] = 11替换成下面格式
this.$set(item, 'sex', 11)
*/
}
}
}
</script>
<style scoped>
</style>
以上就是我个人的理解以及相关测试,如有理解错误欢迎指正