千家信息网

Vue2响应式系统之set和delete怎么用

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,今天小编给大家分享一下Vue2响应式系统之set和delete怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收
千家信息网最后更新 2026年11月01日Vue2响应式系统之set和delete怎么用

今天小编给大家分享一下Vue2响应式系统之set和delete怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

1、数组集

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;

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

可以先思考一下。

答案是否定的,数组我们只能通过重写的 、 等方法去触发更新,详见pushspliceVue2响应式系统之数组 。

如果我们想要替换数组某个元素的话可以转一下弯,通过 去实现。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 doesn't * 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);

2、数组 del

同数组 ,我们顺便提供一个 的方法,支持数组响应式的删除某个元素。setdel

/** * 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 是对象的情况    // ...}

3、对象 set

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);};new Watcher(updateComponent);data.obj.c = 3;

updateComponent 方法中虽然使用了 的 属性,但是在调用 之前, 中并没有 属性,所以 属性不是响应式的。objcobservedata.objcc

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

如果想要变成响应式的话,一种方法就是在最开始就定义 属性。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;

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

/** * Set a property on an object. Adds the new property and * triggers change notification if the property doesn't * 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);

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

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

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

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(); // 手动调用 Watcherdata.obj.c = 4;

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

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

可以看到 里也有个 ,这个其实当时是为数组准备的,参考 objDepVue2响应式系统之数组,但 的 什么都没收集。objdep

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

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) {                      /******新位置 *************************/                                childOb.dep.depend();                      /**********************************/                    if (Array.isArray(value)) {                       // childOb.dep.depend(); //原来的位置                        dependArray(value);                    }                }            }            return value;        },        set: function reactiveSetter(newVal) {            const value = getter ? getter.call(obj) : val;            if (setter) {                setter.call(obj, newVal);            } else {                val = newVal;            }            childOb = !shallow && observe(newVal);            dep.notify();        },    });}function dependArray(value) {    for (let e, i = 0, l = value.length; i < l; i++) {        e = value[i];          /******新位置 *************************/        e && e.__ob__ && e.__ob__.dep.depend();          /**********************************/        if (Array.isArray(e)) {           //  e && e.__ob__ && e.__ob__.dep.depend(); // 原位置            dependArray(e);        }    }}

因为读取 属性,一定先会读取 属性,即 。 也同理。aobjdata.obj.ab

所以通过上边的修改, 的 会收集到它的所有属性的依赖,也就是这里的 、 的依赖,但因为 和 的依赖是相同的,所以收集到一个依赖。objdepabab

但其实我们并不知道 被哪些 依赖,我们只知道和 同属于一个对象的 和 被哪些 依赖,但大概率 也会被其中的 依赖。cWatchercabWatchercWatcher

所以我们可以在 中手动执行一下 的 ,依赖 的 大概率会被执行,相应的 也会成功收集到依赖。setobjDepcWatcherc

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;    }    defineReactive(target, key, val);   /******新增 *************************/    ob.dep.notify()     /************************************/    return val;}

回到最开始的代码:

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);

执行完后 除了变为响应式的,也成功触发了 执行,并且收集到了 。cWatcherWatcher

此时如果修改 的值,也会成功触发 的执行了。cWatcher

4、对象 del

有了上边的了解,删除就很好解决了。

如果要删除 属性,删除后执行下它相应的 就可以。但 的 是存在闭包中的,我们并不能拿到。aDepaDep

退而求其次,我们可以去执行 属性所在的对象 的 就可以了。aobjDep

/** * Delete a property and trigger change if necessary. */export function del(target, key) {    if (Array.isArray(target)) {        target.splice(key, 1);        return;    }    // targe 是对象的情况    const ob = target.__ob__;    if (!hasOwn(target, key)) {        return;    }    delete target[key];    if (!ob) {        return;    }    ob.dep.notify();}

以上就是"Vue2响应式系统之set和delete怎么用"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

属性 对象 数组 方法 情况 系统 手动 知识 篇文章 成功 位置 就是 上边 代码 元素 内容 数据 时候 概率 用户 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 工业互联网科技新基建 鑫亿盛互联网科技 睿民互联网科技 顺玮阁互联网科技 苏州大垚互联网科技 互联网科技网站 互联网科技宣传片 恒生科技互联网指数分析 福州新华互联网科技学校 知乎 青岛科技大学互联网大赛研究生 开一家科技互联网公司需要多少钱 世界互联网领先科技成果获奖 徐州市互联网科技有限公司 沐思想互联网科技有限公司 北京市互联网新科技 互联网科技实习生岗位 富国互联网金融科技混合基金 银川新华互联网科技学校是国营吗 盐城市攀科互联网科技有限公司 互联网 科技节活动 微视频大赛 上海睿民互联网科技有限公司 互联网扶贫科技 远信互联网科技 互联网科技的未来发展 互联网科技论坛 须眉科技是互联网公司吗 成都铂石互联网科技做什么的 互联网科技商业 山东蛋芒互联网科技有限公司 广东猫王互联网科技有限公司电话
0