In "Analog vue data-driven 2", we implemented a observer constructor that allows you to listen to all the properties in the data you have already had.
but what if we want to add a property to an object?
As follows:
Wouldn't it be that the new Infor property, and its object properties, was not being monitored.
at this point, what should be done?
Through the daytime Vue source code, found that he is using the additional attribute method $set implementation.
That is, if we use the usual method to add properties to an object (above), we cannot know and monitor it, so we extend a $set method for each object, which is used for additional attributes, as follows:
Data.user. $set (' infor ', {msg: ' happy '});
Well, here we go together to implement this $set method.
Ii. realization of $set method |
First, we have to create a constant extendobj object that binds the $set method to it.
You might wonder, why do we need a Extendobj object? Just assign the $set function to every object that needs listening.
Yes, that's OK, but as demand grows, what if we want to extend other methods for each listener? Do you want to go to the observer inside for the object, each assigned value?
So, create a constant Extendobj object, as follows:
Const EXTENDOBJ = {};
Because, we bind the $set to the extendobj, and let the $set be non-enumerable, so we use the Object.defineproperty, the solid extract it, as a method as follows:
function proxyobject (obj, Key, Val, Enume) { object.defineproperty (obj, key, { value:val, !!) Enume, true , true }); };
Next, the implementation of the $set method, the overall structure is as follows:
function (Key, Val) { //Thispoints to extendobj if(this. hasOwnProperty ( Key) { return; } Else { /* TODO: Listen for the key property in Extendobj, and if the key property value is an object, listen again for the key property value */ } });
See the above TODO comment, whether it is familiar, is not in the "Analog Vue Data Driven 2" met, through the Observer.prototype.convert monitoring key property, through the new Observer listen again key property value is not finished.
Yes, but once this is done, it is not as good as the "direct $set to the listener" issue we mentioned above, coupled with too much coupling and difficult to maintain as demand increases.
solid and, here is a little trick: give each Listener object a $observer attribute in the Observer module, whose value points to the observer instance itself, as follows:
//Observer.jsP.walk =function(data) {Let keys=Object.keys (data); Keys.foreach (Key={let Val=Data[key]; if(typeofval = = = ' object '){ NewObserver (Val); } This. Convert (Key, Val); }); //$Observer Property points to the Observer self instanceData. $Observer = This;}//added a observe methodP.observe =function(data) {if(typeofdata = = = ' object '){ NewObserver (data); } }
Well, after this, the overall implementation of the $set is as follows:
function (Key, Val) { if(this. hasOwnProperty (Key)) { return; } Else { proxyobject (thistrue); This . $Observer; Ob.observe (val); Ob.convert (Key, Val); } });
Here, a simple $set method is built.
As we mentioned above, a constant Extendobj object is needed for better code management. And, so far, the object that needs to listen does not extend the $set method, so, the following thing is to achieve the above effect, as follows:
// Observer.js function Observer (data) { if(!) ( This instanceof Observer)) { returnnew Observer (data); } // point the Listener's hidden pointer to our Extendobj object data.__proto__ = extendobj; this. data = data; This . Walk (data); }
Okay, all over, let's test it:
<Scriptsrc= "./extendobj.js"></Script><Scriptsrc= "./observer.js"></Script><Script>Let data={User: {name:'Monkey', Age: -}, Lover: {name:'Dorie', Age: at } }; Observer (data);</Script>
The effect is as follows:
Perfect, see GitHub for the full code.
Analog Vue Data Driver 3