Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the Branch switching of Vue2 responsive system

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces the relevant knowledge of "how to realize the branch switching of Vue2 responsive system". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

Scene

Let's consider what the following code will output.

Import {observe} from ". / reactive"; import Watcher from ". / watcher"; const data = {text: "hello, world", ok: true,}; observe (data); const updateComponent = () = > {console.log ("received", data.ok? Data.text: "not");}; new Watcher (updateComponent); / / updateComponent execute the function once, output hello, worlddata.ok = false; / / updateComponent execute the function once, output notdata.text = "hello, liang"; / / will updateComponent execute it?

Let's sort it out step by step:

Observer (data)

Neutralizers are intercepted, and each initializes an instance to hold the objects that depend on them. Datatextokget 、 setDepWatcher

New Watcher (updateComponent)

In this step, the function is executed, and all object properties used in the execution are collected into the corresponding object properties. UpdateComponentWatcherDep

Of course, the one here is actually the same, so the pointing arrow is used. Watcher

Data.ok = false

This step is triggered to execute everything in the process, which is executed once at this time. SetDepWatcherupdateComponent

Execution rereads the properties in, triggers, and then continues the collection. UpdateComponentdatagetWatcher

When re-executing the function: updateComponent

Const updateComponent = () = > {console.log ("received", data.ok? Data.text: "not");}

Because the value of the value becomes, it will not be triggered, and it will not change. Data.okfalsedata.textgettextDep

It will continue to execute and trigger the collection, but because we are using an array, the two collected at this time are actually the same. There is a problem here, which will lead to repeated execution. We will solve it later. Data.okgetWatcherDepWacherupdateComponent

Data.text = "hello, liang"

When this sentence is executed, it will be triggered, so it will be executed once. But from the point of view of the code, since the function has no effect on the output, this execution is actually not necessary. TextsetupdateComponentupdateComponentdata.okfalsedata.text

The reason for the execution is that the read was performed for the first time and thus collected, and on the second execution, although it was not read, the previous one was not cleared, so the change will still be executed this time. UpdateComponentdata.textWatcherupdateComponentdata.textWatcherdata.textupdateComponent

So what we need is that when re-executing, if it is no longer dependent on something, we need to remove the current from that. UpdateComponentWatcherDepWatcherDep

problem

To sum up, there are two things we need to do.

To heavy, do not repeat the collection. DepWatcher

Reset, if the attribute has no effect on the (in other words, the attribute will no longer be read), it should be deleted from the attribute. DepWacherWatcherupdateComponentWatcherDep

Deweighting

There are two ways to remove weight:

The array in Dep is replaced by. SubsSet

Each object is introduced, all are recorded in the object, and the next time the dependency is re-collected, if it already exists, it will no longer be collected. DepidWatcherDepidDepidWatcher

The scheme is used in the Vue2 source code. Here we implement: 2.

The Dep class only needs to be introduced. Id

/ * change * * / let uid = 0 * static target; / / function subs; / / dependent function id that is currently executing / / Dep object ID constructor () {/ * change * / this.id = uid++; / * * / this.subs = [] / / Save all functions that need to be executed} addSub (sub) {this.subs.push (sub);} depend () {if (Dep.target) {/ / delegate to Dep.target to call 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(); } /** * Evaluate the getter, and re-collect dependencies. */ get() { Dep.target = this; // 保存包装了当前正在执行的函数的 Watcher let value; try { value = this.getter.call(); } catch (e) { throw e; } finally { this.cleanupDeps(); } return value; } /** * Add a dependency to this directive. */ addDep(dep) { /*************改动***************************/ const id = dep.id; if (!this.depIds.has(id)) { dep.addSub(this); } /****************************************/ } /** * Subscriber interface. * Will be called when a dependency changes. */ update() { this.run(); } /** * Scheduler job interface. * Will be called by the scheduler. */ run() { this.get(); }}重置 同样是两个方案: 全量式移除,保存 所影响的所有 对象,当重新收集 的前,把当前 从记录中的所有 对象中移除。WatcherDepWatcherWatcherDep 增量式移除,重新收集依赖时,用一个新的变量记录所有的 对象,之后再和旧的 对象列表比对,如果新的中没有,旧的中有,就将当前 从该 对象中移除。DepDepWatcherDep Vue2 中采用的是方案 ,这里也实现下。2 首先是 类,我们需要提供一个 方法。DepremoveSub import { remove } from "./util";/*export function remove(arr, item) { if (arr.length) { const index = arr.indexOf(item); if (index >

-1) {return arr.splice (index, 1);} * / let uid = 0 * / export default class Dep {static target; / / currently executing function subs; / / dependent function id; / / Dep object ID constructor () {this.id = uid++; this.subs = [] / / Save all functions that need to be executed} addSub (sub) {this.subs.push (sub);} / * add * / removeSub (sub) {remove (this.subs, sub) } / * * / depend () {if (Dep.target) {/ / delegate to Dep.target to call 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(); } /** * Evaluate the getter, and re-collect dependencies. */ get() { Dep.target = this; // 保存包装了当前正在执行的函数的 Watcher let value; try { value = this.getter.call(); } catch (e) { throw e; } finally { /*************新增************************/ this.cleanupDeps(); /****************************************/ } return value; } /** * Add a dependency to this directive. */ 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); } } /****************************************/ } /** * Clean up for dependency collection. */ /*************新增************************/ 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; } /****************************************/ /** * Subscriber interface. * Will be called when a dependency changes. */ update() { this.run(); } /** * Scheduler job interface. * Will be called by the scheduler. */ run() { this.get(); }}测试 回到开头的代码 import { observe } from "./reactive";import Watcher from "./watcher";const data = { text: "hello, world", ok: true,};observe(data);const updateComponent = () =>

{console.log ("copy", data.ok? Data.text: "not");}; new Watcher (updateComponent); / / updateComponent execute the function once, output hello, worlddata.ok = false; / / updateComponent execute the function once, output notdata.text = "hello, liang"; / / will updateComponent execute it?

If you modify it at this time, it will not be executed again, because on the second execution, we have cleared the contents in. Data.textupdateComponentdata.textDepWatcher

This is the end of the content of "how to achieve branch switching of Vue2 responsive system". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report