返回顶部
首页 > 资讯 > 精选 >Vue2响应式系统之分支切换怎么实现
  • 414
分享到

Vue2响应式系统之分支切换怎么实现

2023-06-30 01:06:23 414人浏览 八月长安
摘要

本篇内容介绍了“Vue2响应式系统之分支切换怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!场景我们考虑一下下边的代码会输出什么。im

本篇内容介绍了“Vue2响应式系统之分支切换怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    场景

    我们考虑一下下边的代码会输出什么。

    import { observe } from "./Reactive";import Watcher from "./watcher";const data = {    text: "hello, world",    ok: true,};observe(data);const updateComponent = () => {    console.log("收到", data.ok ? data.text : "not");};new Watcher(updateComponent); // updateComponent 执行一次函数,输出 hello, worlddata.ok = false; // updateComponent 执行一次函数,输出 notdata.text = "hello, liang"; // updateComponent 会执行吗?

    我们来一步一步理清:

    observer(data)

    拦截了 中 和 的 ,并且各自初始化了一个 实例,用来保存依赖它们的 对象。datatextokget、setDepWatcher

    Vue2响应式系统之分支切换怎么实现

    new Watcher(updateComponent)

    这一步会执行 函数,执行过程中用到的所有对象属性,会将 收集到相应对象属性中的 中。updateComponentWatcherDep

    Vue2响应式系统之分支切换怎么实现

    当然这里的 其实是同一个,所以用了指向的箭头。Watcher

    data.ok = false

    这一步会触发 ,从而执行 中所有的 ,此时就会执行一次 。setDepWatcherupdateComponent

    执行 就会重新读取 中的属性,触发 ,然后继续收集 。updateComponentdatagetWatcher

    Vue2响应式系统之分支切换怎么实现

    重新执行 函数 的时候:updateComponent

    const updateComponent = () => {    console.log("收到", data.ok ? data.text : "not");};

    因为 的值变为 ,所以就不会触发 的 , 的 就不会变化了。data.okfalsedata.textgettextDep

    而 会继续执行,触发 收集 ,但由于我们 中使用的是数组,此时收集到的两个 其实是同一个,这里是有问题,会导致 重复执行,一会儿我们来解决下。data.okgetWatcherDepWacherupdateComponent

    data.text = "hello, liang"

    执行这句的时候,会触发 的 ,所以会执行一次 。但从代码来看 函数中由于 为 , 对输出没有任何影响,这次执行其实是没有必要的。textsetupdateComponentupdateComponentdata.okfalsedata.text

    之所以执行了,是因为第一次执行 读取了 从而收集了 ,第二次执行 的时候, 虽然没有读到,但之前的 也没有清除掉,所以这一次改变 的时候 依旧会执行。updateComponentdata.textWatcherupdateComponentdata.textWatcherdata.textupdateComponent

    所以我们需要的就是当重新执行 的时候,如果 已经不依赖于某个 了,我们需要将当前 从该 中移除掉。updateComponentWatcherDepWatcherDep

    Vue2响应式系统之分支切换怎么实现

    问题

    总结下来我们需要做两件事情。

    • 去重, 中不要重复收集 。DepWatcher

    • 重置,如果该属性对 中的 已经没有影响了(换句话就是, 中的 已经不会读取到该属性了 ),就将该 从该属性的 中删除。DepWacherWatcherupdateComponentWatcherDep

    去重

    去重的话有两种方案:

    • Dep 中的 数组换为 。subsSet

    • 每个 对象引入 , 对象中记录所有的 的 ,下次重新收集依赖的时候,如果 的 已经存在,就不再收集该 了。DepidWatcherDepidDepidWatcher

    Vue2 源码中采用的是方案 这里我们实现下:2

    Dep 类的话只需要引入 即可。id

    let uid = 0;export default class Dep {    static target; //当前在执行的函数    subs; // 依赖的函数  id; // Dep 对象标识    constructor() {              this.id = uid++;              this.subs = []; // 保存所有需要执行的函数    }    addSub(sub) {        this.subs.push(sub);    }    depend() {        if (Dep.target) {            // 委托给 Dep.target 去调用 addSub            Dep.target.aDDDep(this);        }    }    notify() {        for (let i = 0, l = this.subs.length; i < l; i++) {            this.subs[i].update();        }    }}Dep.target = null; // 静态变量,全局唯一

    在 中,我们引入 来记录所有的 。Watcherthis.depIdsid

    import Dep from "./dep";export default class Watcher {  constructor(Fn) {    this.getter = Fn;        this.depIds = new Set(); // 拥有 has 函数可以判断是否存在某个 id        this.get();  }    get() {    Dep.target = this; // 保存包装了当前正在执行的函数的 Watcher    let value;    try {      value = this.getter.call();    } catch (e) {      throw e;    } finally {      this.cleanupDeps();    }    return value;  }    addDep(dep) {        const id = dep.id;    if (!this.depIds.has(id)) {      dep.addSub(this);    }      }    update() {    this.run();  }    run() {    this.get();  }}

    重置

    同样是两个方案:

    • 全量式移除,保存 所影响的所有 对象,当重新收集 的前,把当前 从记录中的所有 对象中移除。WatcherDepWatcherWatcherDep

    • 增量式移除,重新收集依赖时,用一个新的变量记录所有的 对象,之后再和旧的 对象列表比对,如果新的中没有,旧的中有,就将当前 从该 对象中移除。DepDepWatcherDep

    Vue2 中采用的是方案 ,这里也实现下。2

    首先是 类,我们需要提供一个 方法。DepremoveSub

    import { remove } from "./util";let uid = 0;export default class Dep {    static target; //当前在执行的函数    subs; // 依赖的函数    id; // Dep 对象标识    constructor() {        this.id = uid++;        this.subs = []; // 保存所有需要执行的函数    }    addSub(sub) {        this.subs.push(sub);    }      removeSub(sub) {        remove(this.subs, sub);    }      depend() {        if (Dep.target) {            // 委托给 Dep.target 去调用 addSub            Dep.target.addDep(this);        }    }    notify() {        for (let i = 0, l = this.subs.length; i < l; i++) {            this.subs[i].update();        }    }}Dep.target = null; // 静态变量,全局唯一

    然后是 类,我们引入 来保存所有的旧 对象,引入 来保存所有的新 对象。Watcherthis.depsDepthis.newDepsDep

    import Dep from "./dep";export default class Watcher {    constructor(Fn) {        this.getter = Fn;        this.depIds = new Set(); // 拥有 has 函数可以判断是否存在某个 id              this.deps = [];        this.newDeps = []; // 记录新一次的依赖        this.newDepIds = new Set();              this.get();    }        get() {        Dep.target = this; // 保存包装了当前正在执行的函数的 Watcher        let value;        try {            value = this.getter.call();        } catch (e) {            throw e;        } finally {                      this.cleanupDeps();                  }        return value;    }        addDep(dep) {        const id = dep.id;              // 新的依赖已经存在的话,同样不需要继续保存        if (!this.newDepIds.has(id)) {            this.newDepIds.add(id);            this.newDeps.push(dep);            if (!this.depIds.has(id)) {                dep.addSub(this);            }        }          }          cleanupDeps() {        let i = this.deps.length;        // 比对新旧列表,找到旧列表里有,但新列表里没有,来移除相应 Watcher        while (i--) {            const dep = this.deps[i];            if (!this.newDepIds.has(dep.id)) {                dep.removeSub(this);            }        }        // 新的列表赋值给旧的,新的列表清空        let tmp = this.depIds;        this.depIds = this.newDepIds;        this.newDepIds = tmp;        this.newDepIds.clear();        tmp = this.deps;        this.deps = this.newDeps;        this.newDeps = tmp;        this.newDeps.length = 0;    }          update() {        this.run();    }        run() {        this.get();    }}

    测试

    回到开头的代码

    import { observe } from "./reactive";import Watcher from "./watcher";const data = {    text: "hello, world",    ok: true,};observe(data);const updateComponent = () => {    console.log("收到", data.ok ? data.text : "not");};new Watcher(updateComponent); // updateComponent 执行一次函数,输出 hello, worlddata.ok = false; // updateComponent 执行一次函数,输出 notdata.text = "hello, liang"; // updateComponent 会执行吗?

    此时 修改的话就不会再执行 了,因为第二次执行的时候,我们把 中 里的 清除了。data.textupdateComponentdata.textDepWatcher

    “Vue2响应式系统之分支切换怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

    --结束END--

    本文标题: Vue2响应式系统之分支切换怎么实现

    本文链接: https://lsjlt.com/news/326951.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • Vue2响应式系统之分支切换怎么实现
      本篇内容介绍了“Vue2响应式系统之分支切换怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!场景我们考虑一下下边的代码会输出什么。im...
      99+
      2023-06-30
    • Vue2 响应式系统之分支切换
      目录场景observer(data)new Watcher(updateComponent)data.ok = falsedata.text = "hello, ...
      99+
      2024-04-02
    • Vue2响应式系统之深度响应怎么实现
      本文小编为大家详细介绍“Vue2响应式系统之深度响应怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue2响应式系统之深度响应怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1、场景import&...
      99+
      2023-06-30
    • Vue2响应式系统之嵌套怎么实现
      这篇“Vue2响应式系统之嵌套怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue2响应式系统之嵌套怎么实现”文章吧...
      99+
      2023-06-30
    • Vue2响应式系统之异步队列怎么实现
      这篇“Vue2响应式系统之异步队列怎么实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue2响应式系统之异步队列怎么实现...
      99+
      2023-06-30
    • Vue2 响应式系统之深度响应
      目录1、场景2、方案3、场景24、总结1、场景 import { observe } from "./reactive"; import Watcher from "./watche...
      99+
      2024-04-02
    • Vue2响应式系统之嵌套
      目录1、场景2、执行过程3、修复4、测试5、总结1、场景 在 开发中肯定存在组件嵌套组件的情况,类似于下边的样子。Vue <!-- parent-component ...
      99+
      2024-04-02
    • Vue2 响应式系统之数组
      目录1、场景2、场景 23、方案3、收集依赖代码实现4、通知依赖代码实现5、测试6、总结本文接Vue2响应式系统 、Vue2 响应式系统之分支切换  ,...
      99+
      2024-04-02
    • Vue2响应式系统之set和delete
      目录1、数组集2、数组 del3、对象 set4、对象 del5、总结1、数组集 import { observe } from "./reactive"; import Watch...
      99+
      2024-04-02
    • Vue2响应式系统之set和delete怎么用
      今天小编给大家分享一下Vue2响应式系统之set和delete怎么用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。...
      99+
      2023-06-30
    • Vue2响应式系统之怎么让数组生效
      这篇文章主要介绍了Vue2响应式系统之怎么让数组生效的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue2响应式系统之怎么让数组生效文章都会有所收获,下面我们一起来看看吧。1、场景import {&n...
      99+
      2023-06-30
    • Vue2 响应式系统之异步队列
      目录场景解决方案代码实现执行结果总结试想一下如果这里的 console.log 是渲染页面,那改变一次值就刷新一下页面,会造成严重的性能问题,页面也会不停的改变。 场景 import...
      99+
      2024-04-02
    • Vue2响应式系统有什么用
      这篇文章主要讲解了“Vue2响应式系统有什么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Vue2响应式系统有什么用”吧!一、响应式系统要干什么回到最简单的代码:data =&n...
      99+
      2023-06-30
    • vue2基本响应式实现方式之让数组也变成响应式
      目录vue2让数组也变成响应式vue2中的响应式原理有三点 解决缺点的方法总结vue2让数组也变成响应式 之前的代码有个问题,就是操作数组数据的时候,不会触发set let...
      99+
      2023-05-17
      vue2基本响应式 vue2数组 vue2数组变响应式
    • Vue3响应式系统怎么实现computed
      首先,我们简单回顾一下:响应式系统的核心就是一个 WeakMap --- Map --- Set 的数据结构。WeakMap 的 key 是原对象,value 是响应式的 Map。这样当对象销毁的时候,对应的 Map 也会销毁。Map 的 ...
      99+
      2023-05-15
      Vue3 computed
    • 使用Java怎么实现响应式系统
      使用Java怎么实现响应式系统?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。初识响应式系统ReactiveX的本质就是Observer+Iterator+函数编程+异步。是一个...
      99+
      2023-06-15
    • Vue3 响应式系统实现 computed
      目录前言实现 computed总结前言 上篇文章我们实现了基本的响应式系统,这篇文章继续实现 computed。 首先,我们简单回顾一下: 响应式系统的核心就是一个 WeakMap ...
      99+
      2024-04-02
    • vue2和vue3数据响应式原理分析及如何实现
      今天就跟大家聊聊有关vue2和vue3数据响应式原理分析及如何实现,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。数据响应式视图跟数据是自动更新的,数据更新的时候视图是自动的更新的追踪...
      99+
      2023-06-22
    • Vue3响应式系统如何实现computed
      这篇“Vue3响应式系统如何实现computed”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Vue3响应式系统如何实现co...
      99+
      2023-07-06
    • Win10系统怎么切换黑暗模式
      今天小编给大家分享一下Win10系统怎么切换黑暗模式的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。win10系统切换黑暗模式...
      99+
      2023-07-01
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作