您现在的位置是:亿华云 > 数据库

Vue2剥丝抽茧-响应式系统之Set和的Delete

亿华云2025-10-09 03:25:04【数据库】1人已围观

简介数组setimport { observe } from "./reactive";import Watcher from "./watcher";const data = {list: [1, 2]

数组setimport { observe } from "./reactive";

import Watcher from "./watcher";

const data = {

list: [1,丝抽 2],

};

observe(data);

const updateComponent = () => {

console.log(data.list);

};

new Watcher(updateComponent);

list[0] = 3;

list[0] 会触发 updateComponent 的重新执行吗?

可以先思考一下。

... ...

答案是茧响否定的,数组我们只能通过重写的应式 push、 splice 等方法去触发更新,系统详见 Vue2剥丝抽茧-响应式系统之数组。丝抽

如果我们想要替换数组某个元素的茧响话可以转一下弯,通过 splice 去实现。应式

import { observe } from "./reactive";

import Watcher from "./watcher";

const data = {

list: [1,系统 2],

};

observe(data);

const updateComponent = () => {

console.log(data.list);

};

new Watcher(updateComponent);

// list[0] = 3;

data.list.splice(0, 1, 3);

每次这样写太麻烦了,我们可以提供一个 set 方法供用户使用。丝抽

/

**

* Set a property on 茧响an object. Adds the new property and

* triggers change notification if the property doesnt

* already exist.

*/

export function set(target, key, val) {

if (Array.isArray(target)) {

target.length = Math.max(target.length, key);

target.splice(key, 1, val);

return val;

}

// targe 是对象的情况

// ...

}

然后我们直接使用 set 方法就可以了。

import { observe,应式 set } from "./reactive";

import Watcher from "./watcher";

const data = {

list: [1, 2],

};

observe(data);

const updateComponent = () => {

console.log(data.list);

};

new Watcher(updateComponent);

// list[0] = 3;

// data.list.splice(0, 1, 3);

set(data.list, 0, 3);数组 del

同数组 set ,我们顺便提供一个 del 的系统方法,支持数组响应式的丝抽删除某个元素。

/

**

* Delete a property and 茧响trigger change if necessary.

*/

export function del(target, key) {

if (Array.isArray(target) && isValidArrayIndex(key)) {

target.splice(key, 1);

return;

}

// targe 是对象的情况

// ...

}

对象 setimport { observe, set, del } from "./reactive";

import Watcher from "./watcher";

const data = {

obj: {

a: 1,

b: 2,

},

};

observe(data);

const updateComponent = () => {

const c = data.obj.c ? data.obj.c : 0;

console.log(data.obj.a + data.obj.b + c);

};

new Watcher(updateComponent);

data.obj.c = 3;

updateComponent 方法中虽然使用了 obj 的 c 属性,但是应式在调用 observe 之前,亿华云计算data.obj 中并没有 c 属性,所以 c 属性不是响应式的。

当我们修改 data.obj.c 的值的时候,并不会触发 updateComponent 的执行。

如果想要变成响应式的话,一种方法就是在最开始就定义 c 属性。

const data = {

obj: {

a: 1,

b: 2,

c: null,

},

};

observe(data);

const updateComponent = () => {

const c = data.obj.c ? data.obj.c : 0;

console.log(data.obj.a + data.obj.b + c);

};

new Watcher(updateComponent);

data.obj.c = 3;

另一种方法就是通过 set 去设置新的属性了,在 set 中我们可以将新添加的属性设置为响应式的。

/

**

* Set a property on an object. Adds the new property and

* triggers change notification if the property doesnt

* already exist.

*/

export function set(target, key, val) {

if (Array.isArray(target)) {

target.length = Math.max(target.length, key);

target.splice(key, 1, val);

return val;

}

// targe 是对象的情况

// key 在 target 中已经存在

if (key in target && !(key in Object.prototype)) {

target[key] = val;

return val;

}

const ob = target.__ob__;

// target 不是响应式数据

if (!ob) {

target[key] = val;

return val;

}

// 将当前 key 变为响应式的

defineReactive(target, key, val);

return val;

}

回到我们之前的程序:

import { observe, set, del } from "./reactive";

import Watcher from "./watcher";

const data = {

obj: {

a: 1,

b: 2,

},

};

observe(data);

const updateComponent = () => {

const c = data.obj.c ? data.obj.c : 0;

console.log(data.obj.a + data.obj.b + c);

};

const ob = new Watcher(updateComponent);

set(data.obj, "c", 3);

虽然通过 set 增加了属性,但是此时 Watcher 并不会重新触发,b2b信息网原因的话我们看下依赖图。

虽然属性 c 拥有了 Dep 对象,但由于没有调用过依赖属性 c 的 Watcher ,所以它并没有收集到依赖。

当然我们可以 set 完手动调用一次相应的 Watcher 。

const data = {

obj: {

a: 1,

b: 2,

},

};

observe(data);

const updateComponent = () => {

const c = data.obj.c ? data.obj.c : 0;

console.log(data.obj.a + data.obj.b + c);

};

const ob = new Watcher(updateComponent);

set(data.obj, "c", 3);

ob.update(); // 手动调用 Watcher

data.obj.c = 4;

这样的话,当执行 data.obj.c = 4 的时候就会触发 Watcher 的执行了。

那么我们能将触发相应的 Watcher 的逻辑放到 set 函数中吗?

可以看到 obj 里也有个 Dep,这个其实当时是为数组准备的,参考 Vue2剥丝抽茧-响应式系统之数组,但 obj 的 dep 什么都没收集。

我们修改一下代码让它也收集一下:

export function defineReactive(obj, key, val, shallow) {

const property = Object.getOwnPropertyDescriptor(obj, key);

// 读取用户可能自己定义了的 get、set

const getter = property && property.get;

const setter = property && property.set;

// val 没有传进来话进行手动赋值

if ((!getter || setter) && arguments.length === 2) {

val = obj[key];

}

const dep = new Dep(); // 持有一个 Dep 对象,用来保存所有依赖于该变量的 Watcher

let childOb = !shallow && observe(val);

Object.defineProperty(obj, key, {

enumerable: true,

configurable: true,

get: function reactiveGetter() {

const value = getter ? getter.call(obj) : val;

if (Dep.target) {

dep.depend();

if (childOb) {

/高防服务器

很赞哦!(48)