摘要:响应式原理看过官方文档的同学,对这张图应该已然相当熟悉了。先撸为敬这里我们用不到行的代码,实现了一个简易的响应式。当然,这里如果不考虑期间的过程,我相信,行代码之内可以搞定。
Vue响应式原理
看过vue官方文档的同学,对这张图应该已然相当熟悉了。
vue的响应式是如何实现的?
听过太多回答,通过Object.defineProperty,可是再详细的问时,对方浑然不知。
先撸为敬const Observer = function(data) { for (let key in data) { defineReactive(data, key); } } const defineReactive = function(obj, key) { const dep = new Dep(); let val = obj[key]; Object.defineProperty(obj, key, { enumerable: true, configurable: true, get() { console.log("in get"); dep.depend(); return val; }, set(newVal) { if (newVal === val) { return; } val = newVal; dep.notify(); } }); } const observe = function(data) { return new Observer(data); } const Vue = function(options) { const self = this; if (options && typeof options.data === "function") { this._data = options.data.apply(this); } this.mount = function() { new Watcher(self, self.render); } this.render = function() { with(self) { _data.text; } } observe(this._data); } const Watcher = function(vm, fn) { const self = this; this.vm = vm; Dep.target = this; this.addDep = function(dep) { dep.addSub(self); } this.update = function() { console.log("in watcher update"); fn(); } this.value = fn(); Dep.target = null; } const Dep = function() { const self = this; this.target = null; this.subs = []; this.depend = function() { if (Dep.target) { Dep.target.addDep(self); } } this.addSub = function(watcher) { self.subs.push(watcher); } this.notify = function() { for (let i = 0; i < self.subs.length; i += 1) { self.subs[i].update(); } } } const vue = new Vue({ data() { return { text: "hello world" }; } }) vue.mount(); // in get vue._data.text = "123"; // in watcher update /n in get
这里我们用不到100行的代码,实现了一个简易的vue响应式。当然,这里如果不考虑期间的过程,我相信,40行代码之内可以搞定。但是我这里不想省略,为什么呢?我怕你把其中的过程自动忽略掉,怕别人问你相关东西的时候,明明自己看过了,却被怼的哑口无言。总之,我是为了你好,多喝热水。
Dep的作用是什么?依赖收集器,这不是官方的名字蛤,我自己起的,为了好记。
用两个例子来看看依赖收集器的作用吧。
例子1,毫无意义的渲染是不是没必要?
const vm = new Vue({ data() { return { text: "hello world", text2: "hey", } } })
当vm.text2的值发生变化时,会再次调用render,而template中却没有使用text2,所以这里处理render是不是毫无意义?
针对这个例子还记得我们上面模拟实现的没,在Vue的render函数中,我们调用了本次渲染相关的值,所以,与渲染无关的值,并不会触发get,也就不会在依赖收集器中添加到监听(addSub方法不会触发),即使调用set赋值,notify中的subs也是空的。OK,继续回归demo,来一小波测试去印证下我说的吧。
const vue = new Vue({ data() { return { text: "hello world", text2: "hey" }; } }) vue.mount(); // in get vue._data.text = "456"; // nothing vue._data.text2 = "123"; // in watcher update /n in get
例子2,多个Vue实例引用同一个data时,通知谁?是不是应该俩都通知?
let commonData = { text: "hello world" }; const vm1 = new Vue({ data() { return commonData; } }) const vm2 = new Vue({ data() { return commonData; } }) vm1.mount(); // in get vm2.mount(); // in get commonData.text = "hey" // 输出了两次 in watcher update /n in get
老规矩,自己代入进去试试。
希望通过这两个例子,你已经大概清楚了Dep的作用,有没有原来就那么回事的感觉?有就对了。总结一下吧(以下依赖收集器实为Dep):
vue将data初始化为一个Observer并对对象中的每个值,重写了其中的get、set,data中的每个key,都有一个独立的依赖收集器。
在get中,向依赖收集器添加了监听
在mount时,实例了一个Wathcer,将收集器的目标指向了当前Watcher
在data值发生变更时,触发set,触发了依赖收集器中的所有监听的更新,来触发Watcher.update
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94576.html
摘要:紧接着发现,于是又停了,浏览器下载并执行完,继续。,发现,遂将中文字展示了出来。的执行时间是在所有元素解析完成之后,事件触发之前。的执行时间是在当前脚本下载完成后,所以多个是执行顺序是不固定的。至此,完美的结构出炉了。 现代浏览器性能优化-JS篇 众所周知,JS的加载和执行会阻塞浏览器渲染,所以目前业界普遍推荐把script放到之前,以解决js执行时找不到dom等问题。但随着现代浏览器...
摘要:紧接着发现,于是又停了,浏览器下载并执行完,继续。,发现,遂将中文字展示了出来。的执行时间是在所有元素解析完成之后,事件触发之前。的执行时间是在当前脚本下载完成后,所以多个是执行顺序是不固定的。至此,完美的结构出炉了。 现代浏览器性能优化-JS篇 众所周知,JS的加载和执行会阻塞浏览器渲染,所以目前业界普遍推荐把script放到之前,以解决js执行时找不到dom等问题。但随着现代浏览器...
摘要:当触发异常的字节码的索引值在某个异常表条目的监控范围内,虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。 作者:李瑞杰目前就职于阿里巴巴,狂热JVM爱好者让我们准备一个函数:showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反编译他的字节码:showImg(https://user-gold-cd...
摘要:当触发异常的字节码的索引值在某个异常表条目的监控范围内,虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。 作者:李瑞杰目前就职于阿里巴巴,狂热JVM爱好者让我们准备一个函数:showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反编译他的字节码:showImg(https://user-gold-cd...
摘要:当触发异常的字节码的索引值在某个异常表条目的监控范围内,虚拟机会判断所抛出的异常和该条目想要捕获的异常是否匹配。 作者:李瑞杰目前就职于阿里巴巴,狂热JVM爱好者让我们准备一个函数:showImg(https://user-gold-cdn.xitu.io/2019/5/19/16acbce35adfefb7);然后,反编译他的字节码:showImg(https://user-gold-cd...
阅读 2830·2023-04-26 01:02
阅读 1839·2021-11-17 09:38
阅读 760·2021-09-22 15:54
阅读 2885·2021-09-22 15:29
阅读 869·2021-09-22 10:02
阅读 3401·2019-08-30 15:54
阅读 1995·2019-08-30 15:44
阅读 1572·2019-08-26 13:46