1. Preface
At the end of the essay "Simulating Vue Data Driver 1", we talked about what if the monitored property is an object? Then wouldn’t it be possible to monitor other properties in this object?
is as follows:
If the name and age attributes in user change, how do you know they have changed?
Today, let’s solve this problem.
By reading the Vue source code, I found that he uses the Observer constructor to create an Observer object for each object to monitor the data. If the attribute in the data is an object, then it is monitored through the Observer. .
In fact, the core idea is pre-order traversal of the tree (for trees, please refer to here). If we graph the data in the above Demo, it will become more clear, as follows:
Okay, now that we have clarified the general idea, let’s do it together. Create an Observer.
2. Observer structure
The overall structure of Observer is as follows:
function Observer(data){ //如若this不是Observer对象,即创建一个 if(!(this instanceof Observer)){ return new Observer(data); } this.data = data; this.walk(data); } let p = Observer.prototype = Object.create(null); p.walk = function(data){ /* TODO:监听data数据中的所有属性, 并查看data中属性值是否为对象, 若为对象,就创建一个Observer实例 */ } p.convert = function(key, val){ //TODO:通过Object.defineProperty监听数据 }
Okay, let’s complete the walk and convert methods together Bar.
-walk-
First, we implement monitoring of all properties in the data object in the walk method, as follows:
p.walk = function(data){ let keys = Object.keys(data); keys.forEach( key => { let val = data[key]; this.convert(key, val); }); }
And, because There may be another object in the attribute, so we need to listen to them.
How to do it?
If it is an object, use the Observer constructor again to process it.
is as follows:
p.walk = function(data){ let keys = Object.keys(data); keys.forEach( key => { let val = data[key]; //如果val为对象,则交给Observer处理 if(typeof val === 'object'){ Observer(val); } this.convert(key, val); }); }
You may have this question, if you directly use Observer to process objects, won't you lose the connection with the parent object?
However, no, because JavaScript points to the address relationship for objects, so how can the association be lost?
-convert-
For the convert method, it is relatively simple. As always, use Object.defineProperty to monitor the data, as follows:
p.convert = function(key, val){ Object.defineProperty(this.data, key, { get: ()=>{ console.log('访问了'+key+' 值为'+val); return val; }, set: (newVal)=>{ console.log('设置了'+key+' 值为'+newVal); if(newVal !== val){ val = newVal; } } }); }
Okay , At this point, a simple Observer has been constructed. Next, we will test whether each attribute has been successfully monitored.
<script src="./observer.js"></script> <script> let data = { user: { name: 'Monkey', age: 24 }, lover: { name: 'Dorie', age: 23 } }; Observer(data); </script>
The effect is as follows:
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope that everyone Duoduo supports PHP Chinese website.
For more Vue data-driven simulation implementation 2 related articles, please pay attention to the PHP Chinese website!