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安全错误 数据库的锁怎样保障安全 java获取数据库中数据 吉利软件开发招聘 灵活用工平台软件开发排名 预防中小学生网络安全知识 怀柔区服务器ups电源 app评论数据库设计 河南gps网络时钟服务器 网络技术考试可以用cmd吗 uci公共数据库 京东软件开发打包 网络安全国内有名教授 国家网络安全宣传周图 我的世界服务器是谁加的 电信动态公网ip服务器 网络安全手抄报新 魔兽服务器维护到几点 软件开发程序员混不下去了 cbm数据库的基本途径 怀旧服赛季服服务器 软件开发人员wbs图 数据库多少表属于大项目 万德数据库怎么找市值 网络安全管理和平台 穿越火线qq安卓服务器 软件开发电商支付系统 义乌工业软件开发项目 根服务器作用 自我鉴定范文软件开发专业 良庆区网络安全知识 dedecms数据库优化