Vue2响应式系统之嵌套怎么实现
这篇"Vue2响应式系统之嵌套怎么实现"文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇"Vue2响应式系统之嵌套怎么实现"文章吧。
1、场景
在 开发中肯定存在组件嵌套组件的情况,类似于下边的样子。Vue
{{ text }} {{ text }}回到我们之前的响应式系统,模拟一下上边的情况:
import { observe } from "./reactive";import Watcher from "./watcher";const data = { text: "hello, world", inner: "内部",};observe(data);const updateMyComponent = () => { console.log("子组件收到:", data.inner);};const updateParentComponent = () => { new Watcher(updateMyComponent); console.log("父组件收到:", data.text);};new Watcher(updateParentComponent);data.text = "hello, liang";可以先 分钟考虑一下上边输出什么?
1首先回忆一下 会做什么操作。
new Watcher第一步是保存当前函数,然后执行当前函数前将全局的 赋值为当前 对象。
Dep.targetWatcher接下来执行 函数的时候,如果读取了相应的属性就会触发 ,从而将当前 收集到该属性的 中。
gettergetWatcherDep2、执行过程
import { observe } from "./reactive";import Watcher from "./watcher";const data = { text: "hello, world", inner: "内部",};observe(data);const updateMyComponent = () => { console.log("子组件收到:", data.inner);};const updateParentComponent = () => { new Watcher(updateMyComponent); console.log("父组件收到:", data.text);};new Watcher(updateParentComponent);data.text = "hello, liang";我们再一步一步理清一下:
new Watcher(updateParentComponent);将 赋值为保存了 函数的 。
Dep.targetupdateParentComponentWatcher接下来执行 函数。
updateParentComponent
new Watcher(updateMyComponent);将 赋值为保存了 函数的 。
Dep.targetupdateMyComponentWatcher接下来执行 函数。
updateMyComponentconst updateMyComponent = () => { console.log("子组件收到:", data.inner);};// 读取了 inner 变量。// data.inner 的 Dep 收集当前 Watcher(保存了 `updateMyComponent` 函数)const updateParentComponent = () => { new Watcher(updateMyComponent); console.log("父组件收到:", data.text);};// 读取了 text 变量。// data.text 的 Dep 收集当前 Watcher (保存了 `updateMyComponent` 函数)
data.text = "hello, liang";触发 的 函数,执行它依赖的 ,而此时是 函数。
textsetWatcherupdateMyComponent所以上边代码最终输出的结果是:
子组件收到: 内部 // new Watcher(updateMyComponent); 时候输出
父组件收到: hello, world // new Watcher(updateParentComponent); 时候输出
子组件收到: 内部 // data.text = "hello, liang"; 输出然而子组件并不依赖 ,依赖 的父组件反而没有执行。
data.textdata.text3、修复
上边的问题出在我们保存当前正在执行 时候使用的是单个变量 。
WatcherDep.target = null; // 静态变量,全局唯一回忆一下学习 语言或者汇编语言的时候对函数参数的处理:
Cfunction b(p) { console.log(p);}function a(p) { b("child"); console.log(p);}a("parent");当函数发生嵌套调用的时候,执行 函数的时候我们会先将参数压入栈中,然后执行 函数,同样将参数压入栈中, 函数执行完毕就将参数出栈。此时回到 函数就能正确取到 参数的值了。
abbap对应于 的收集,我们同样可以使用一个栈来保存,执行函数前将 压入栈,执行函数完毕后将 弹出栈即可。其中, 始终指向栈顶 ,代表当前正在执行的函数。
WatcherWatcherWatcherDep.targetWatcher回到 代码中,我们提供一个压栈和出栈的方法。
Depimport { remove } from "./util";let uid = 0;export default class Dep { ... 省略}Dep.target = null; // 静态变量,全局唯一// The current target watcher being evaluated.// This is globally unique because only one watcher// can be evaluated at a time.const targetStack = [];export function pushTarget(target) { targetStack.push(target); Dep.target = target;}export function popTarget() { targetStack.pop(); Dep.target = targetStack[targetStack.length - 1]; // 赋值为栈顶元素}然后 中,执行函数之前进行入栈,执行后进行出栈。
Watcherimport { pushTarget, popTarget } 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() { /************修改的地方*******************************/ pushTarget(this); // 保存包装了当前正在执行的函数的 Watcher /*******************************************/ let value; try { value = this.getter.call(); } catch (e) { throw e; } finally { /************修改的地方*******************************/ popTarget(); /*******************************************/ this.cleanupDeps(); } return value; } ...}4、测试
回到开头的场景,再来执行一下:
import { observe } from "./reactive";import Watcher from "./watcher";const data = { text: "hello, world", inner: "内部",};observe(data);const updateMyComponent = () => { console.log("子组件收到:", data.inner);};const updateParentComponent = () => { new Watcher(updateMyComponent); console.log("父组件收到:", data.text);};new Watcher(updateParentComponent);data.text = "hello, liang";执行 的时候将 入栈。
new Watcher(updateParentComponent);Watcher进入 函数,执行 的时候将 入栈。
updateParentComponentnew Watcher(updateMyComponent);Watcher执行 函数, 收集当前 ,执行完毕后 出栈。
updateMyComponentdata.innerDep.targetWatcher继续执行 函数, 收集当前 。
updateParentComponentdata.textDep.target此时依赖就变得正常了, 会触发 函数,从而输出如下:
data.textupdateParentComponent子组件收到: 内部
父组件收到: hello, world
子组件收到: 内部
父组件收到: hello, liang以上就是关于"Vue2响应式系统之嵌套怎么实现"这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注行业资讯频道。
函数 组件 时候 输出 内容 参数 变量 系统 上边 接下来 全局 正在 代码 地方 场景 属性 情况 文章 知识 篇文章 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 精品咖啡豆 南京欣网互联网络科技有限公司 中关村互联网科技集团 中资互联网科技 互联网 科技 猪兼强互联网科技 人人互联网科技是培训 开启互联网科技时代小说 深圳国际航运科技和互联网 湖北码尼互联网科技有限公司电话 呼和浩特新华互联网科技学院 广西互联网科技孵化中心 济南有互联网科技公司吗 上海京穆互联网科技有限公司 下一代互联网重大应用科技园 陕西九四连强互联网科技有限公司 版纳互联网科技选哪家 互联网领先科技活动 悟空问答互联网科技 利用互联网等科技手段 广东猪兼强互联网科技有限公司 互联网科技垄断 互联网科技金融公司 九亚互联网科技 未来的互联网科技 苏州大垚互联网科技 中国互联网十大科技股排名 江苏互联网科技小贷 安徽零酒互联网科技有限公司 恒生科技指数 中概互联网