This time I will show you how to implement Vue data responsiveness and what are the things to note. The following is a practical case, let's take a look.
Preface
Vue’s data response mainly relies on Object.defineProperty(), so what is the whole process like? Taking the path of Vue with our own ideas actually means taking the principles of Vue as the end point. Let's reverse the implementation process. The code in this article is a low-configuration version, and many places are not rigorous. For example, if(typeof obj === 'object') is to determine whether obj is an object, although obj may also beArray and other types of data, but for the sake of simplicity, this article will write it directly to represent the judgment object. For arrays, use Array.isArray().
Transform data
Let’s first try to write a function for transforming objects: Why should we write this first? What about functions? Because transforming data is the most basic and important step, all subsequent steps will depend on this step.// 代码 1.1 function defineReactive (obj,key,val) { Object.defineProperty(obj,key,{ enumerable: true, configurable: true, get: function () { return val; }, set: function (newVal) { //判断新值与旧值是否相等 //判断的后半段是为了验证新值与旧值都为NaN的情况 NaN不等于自身 if(newVal === val || (newVal !== newVal && value !== value)){ return ; } val = newVal; } }); }
Process Discussion
After verification, this function was found It can indeed be used. Then let’s discuss the response process:Dependency collection
How do we Do you know what event will be triggered after the data changes? In Vue: Use data => View; Data is used to render the view, so it is the best time to collect dependencies when obtaining data. Vue generates a Dep instance when transforming the data attributes. Used to collect dependencies.// 代码 1.2 class Dep { constructor(){ //订阅的信息 this.subs = []; } addSub(sub){ this.subs.push(sub); } removeSub (sub) { remove(this.subs, sub); } //此方法的作用等同于 this.subs.push(Watcher); depend(){ if (Dep.target) { Dep.target.addDep(this); } } //这个方法就是发布通知了 告诉你 有改变啦 notify(){ const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update(); } } } Dep.target = null;
//代码 1.3 function defineReactive (obj,key,val) { const dep = new Dep(); Object.defineProperty(obj,key,{ enumerable: true, configurable: true, get: function () { if(Dep.target){ //收集依赖 等同于 dep.addSub(Dep.target) dep.depend() } return val; }, set: function (newVal) { if(newVal === val || (newVal !== newVal && val !== val)){ return ; } val = newVal; //发布改变 dep.notify(); } }); }
Verification
It’s time to verify the availability of a wave of codes//代码 1.4 const obj = {};//这一句是不是感觉很熟悉 就相当于初始化vue的data ---- data:{obj:{}}; //低配的不能再低配的watcher对象(源码中是一个类,我这用一个对象代替了) const watcher = { addDep:function (dep) { dep.addSub(this); }, update:function(){ html(); } } //假装这个是渲染页面的 function html () { document.querySelector('body').innerHTML = obj.html; } defineReactive(obj,'html','how are you');//定义响应式的数据 Dep.target = watcher; html();//第一次渲染界面 Dep.target = null;
此时浏览器上的界面是这样的
然后在下打开了控制台开始调试,输入:
obj.html = 'I am fine thank you'
然后就发现,按下回车的那一瞬间,奇迹发生了,页面变成了
结尾
Vue数据响应的设计模式和订阅发布模式有一点像,但是不同,每一个dep实例就是一个订阅中心,每一次发布都会把所有的订阅全部发布出去。
Vue的响应式原理其实还有很大一部分,本文主要讨论了Vue是如何让数据进行响应,但是实际上,一般的数据都是很多的,一个数据被多处使用,改变数据之后观察新值,如何观察、如何订阅、如何调度,都还有很大一部分没有讨论。主要的三个类Dep(收集依赖)、Observer(观察数据)、Watcher(订阅者,若数据有变化通知订阅者),都只提了一点点。
之前写有一篇Vue响应式----数组变异方法,针对Vue中对数组的改造进行讨论。当然之后有更多其他的文章,整个数据响应流程还有很多内容,三个主要的类都还没有讨论完。
其实阅读源码不仅仅是为了知道源码是如何工作的,更重要的是学习作者的思路与方法,我写的文章都不长,希望自己能够每次专注一个点,能够真真实实领悟到这一个点的原理。当然也想控制阅读时间,免得大家看到一半就关闭了。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
The above is the detailed content of How to implement Vue data responsiveness. For more information, please follow other related articles on the PHP Chinese website!