文章目录

前言一、reactive 对比 ref二、直接整体赋值会破坏响应式2.1. 解决方法一:使用push方法2.2. 解决方法二:将数组定义为对象中的一个属性

三、将 reactive 的值 设置为 readonly四、shallowReactive4.1. reactive 是深层的响应式,视图会立刻更新4.2. shallowReactive 是浅层的响应式4.3. 会被其他有视图更新的操作,顺带着一起更新掉

五、源码学习5.2. 学习笔记

六、toRef、toRefs、toRaw

前言

上一篇学习了 ref 全家桶,在此基础上一起学习下 reactive 全家桶

一、reactive 对比 ref

ref 可以接收 所有类型,reactive 只能接收 `object类型(array、object、Map、Set)ref 在取值和赋值时都要通过 .value,reactive 不需要reactive 不能直接整体赋值,因为它是通过proxy创建的响应式对象,直接赋值会 破坏响应式解决方案 1:可以 调用一些原生操作,比如 数组可用 push、pop 等去修改解决方案 2:外面再包上一层

二、直接整体赋值会破坏响应式

import { reactive } from "vue";

let arr = reactive([]);

setTimeout(() => {

arr = [1, 2, 3];

console.log(arr); // 数据变化了,但模板没变化

}, 100);

2.1. 解决方法一:使用push方法

import { reactive } from "vue";

let arr = reactive([]);

setTimeout(() => {

const newArr = [1, 2, 3];

arr.push(...newArr);

console.log(arr);

}, 100);

2.2. 解决方法二:将数组定义为对象中的一个属性

import { reactive } from "vue";

type T = {

arr: Array;

};

let list = reactive({

arr: [],

});

setTimeout(() => {

list.arr = [1, 2, 3];

console.log(list.arr);

}, 100);

三、将 reactive 的值 设置为 readonly

设置为 readonly 后不可修改修改 reactive 源数据,readonly 的值也会受影响

可以看到,两者的值都被修改了:

四、shallowReactive

与上一篇 ref 全家桶 中 shallowRef 十分相似,都是浅层的响应式 修改第一层会触发视图更新,修改深层不会触发视图更新,有其他触发视图更新的操作,也会顺带将其更新(官方回复这并不是一个bug,而是特色)

4.1. reactive 是深层的响应式,视图会立刻更新

import { reactive } from "vue";

const obj2 = reactive({

foo: {

bar: {

name: "xiaoman",

},

},

});

setTimeout(() => {

obj2.foo.bar.name = "blue222222222";

}, 1000);

4.2. shallowReactive 是浅层的响应式

const obj3 = shallowReactive({

foo: {

bar: {

name: "xiaoman",

},

},

});

修改浅层才会触发响应式,会立刻更新:

setTimeout(() => {

obj3.foo = {

bar: {

name: "小满",

},

};

}, 1000);

修改深层可以打印到新值,但视图不会立刻更新:

setTimeout(() => {

// 修改深层不会触发更新

obj3.foo.bar.name = "blue3333333333";

console.log("obj3", obj3); // 打印成功,但是视图不会更新

}, 1000);

4.3. 会被其他有视图更新的操作,顺带着一起更新掉

import { reactive, shallowReactive } from "vue";

const obj2 = reactive({

foo: {

bar: {

name: "xiaoman",

},

},

});

const obj3 = shallowReactive({

foo: {

bar: {

name: "xiaoman",

},

},

});

setTimeout(() => {

// 修改深层不会触发更新

obj3.foo.bar.name = "blue3333333333";

console.log("obj3", obj3);

obj2.foo.bar.name = "blue555555"; // obj2 是 reactive,触发更新视图

}, 1000);

五、源码学习

主要关注 createReactiveObject 函数的逻辑

5.2. 学习笔记

/**

*

* 1、reactivity.d.ts中,关于 reactive 的类型定义:

*

* export declare function reactive(target: T): UnwrapNestedRefs;

*

* 其中 T extends object:即只能传入 object 的子类型

*

* 2、reactivity.cjs.prod.js中,

*

* function reactive(target) {

if (isReadonly(target)) {

return target;

}

.....

* 即:reactive 如果传入只读类型的,会直接返回

*

* 3、createReactiveObject 函数中,

* - 若传入的不是 object 类型,会抛出警告(dev环境)并直接返回;

* - 若传入的是被 proxy 代理过的(并且不是为了将其变为只读),也会直接返回

* - 如果能从缓存中找到,则直接返回(weakMap)

* - 如果在白名单中,也会直接返回,例如 __skip__(后面会讲的 markRaw 处理过的会加一个 __skip__,会跳过proxy代理 )

* - 如果以上条件都没触发,就会进行 proxy代理

*

*/

六、toRef、toRefs、toRaw

toRef、toRefs、toRaw

精彩链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。