代码测试
<template>
<div class='box'>
{{ demo[0]?.a?.b?.c }}
</div>
</template>
<script lang='ts' setup>
import { ref, reactive, computed, onMounted, nextTick, PropType, toRaw } from 'vue';
import { cloneDeep } from "lodash-es"
const obj1 = {
a: {
b: {
c: 1
}
}
}
const arr1 = [obj1, { "a": 3 }, { "a": "slkdjfslkfdjs" }]
console.log(arr1[0] === obj1, "打印结果是true,说明用的是同一块内存引用")
const demo = ref<any>(arr1)
console.log(demo.value[0] === obj1, "打印结果是false,因为demo.value[0] 已经是一个proxy包装的对象了")
console.log(toRaw(demo.value[0]) === obj1, "打印结果是true,说明toRaw不是单纯的拷贝一份对象返回的,而是返回原对象的引用,所以和obj1是对等的")
setTimeout(() => {
obj1.a.b.c = 7
demo.value.map((i, index) => {
console.log(toRaw(i), "原始值")
console.log(obj1, "obj1")
if (index === 0) {
console.log(toRaw(i) === obj1, "slkvnskdjlsfsdfnlsfsjlkfj")
}
if (toRaw(i) === obj1) {
console.log("find found")
// 下面这样也不能触发响应式,因为i是个proxy对象,不能直接赋值,直接赋值会失去proxy,变成一个单纯的对象
//i = obj1;
//下面这样不能使视图发生改变,因为内存是一致的,数据没发生改变,不会触发页面响应式
//i = Object.assign(i, obj1)
//下面这样也可以使视图发生改变,因为深拷贝了一份内存数据,引用发生改变,所以赋值会使vue监听到且比较数据变更不同才会响应式刷新页面
//demo.value[index] = cloneDeep(obj1)
// 下面这样可以使 视图发生改变,i是proxy,需要通过Object.assign 等方式赋值,这样就能响应式,且还是那个proxy对象
//i = Object.assign(i, cloneDeep(obj1))
// 这样也能产生响应式,因为引用地址发生了变化,也就是数据发生了改变,b的引用内存地址发生了改变
//i.a.b = cloneDeep(obj1.a.b)
//下面这样还是不能响应式,因为i.a.b.c发生改变,obj1.a.b.c也同样变为null
/* i.a.b.c = null;
nextTick(() => {
//所以这里赋值还是同样的值赋值同样的值,不会让vue发生视图变更,因为比较结果是一样
i.a.b.c = obj1.a.b.c;
console.log(i.a.b, "sldfjsldjfslk")
}) */
//下面这样就能发生数据不一致的比较变更,从而使视图发生改变
//const copy = cloneDeep(obj1.a.b.c);
const copy = obj1.a.b.c; //如果c是对象或者数组,就需要clone下了,要不然引用地址会一样
i.a.b.c = null;
nextTick(() => {
//这样赋值不一样的数据,就能使视图发生更新,因为null和copy这个变量的数据值不一样
i.a.b.c = copy;
console.log(i.a.b, "sdfsvsdsfsdfsd")
})
}
})
}, 2000)
</script>
<style lang='scss' scoped></style>
结论
- vue能够视图产生变更的2个必要前提:
1、必须通过ref或者reactive进行数据修改
2、ref或者reactive是多层次的对象数据,修改子对象数据后的数据必须和修改前的数据不一致才能被vue识别产生变更。体现再要么内存引用发生变更,要么是基本数据类型的值发生变更, - 没发生响应式的情况
1、修改了ref拷贝的原对象,虽然是同一份内存引用,但是不是通过ref进行修改的,所以不会发生视图变更,但是ref的内存数据确实也改变了。
2、修改了的子对象是一个基本的数据类型,赋值了同样的值也不会发生数据改变,因为vue比较变更后发现没变更就不会执行之徒更新 - 要想视图一定会发生发生更新,务必遵守
1、通过ref或者reactive进行数据修改
2、修改后的数据一定得和修改前的数据不一样,要么进行对象的引用变更,要么对基本数据类型的值进行变更才能响应式
前端工程师、程序员