Objective
Recently, trying to reconstruct the company's existing business code with Vue.js, the modular design and MVVM thought made me deeply addicted to it. But it was a lot of holes, like the update detection after the array bindings described in this article.
I believe we all know that, can be Observer
Watcher
described as vm
a more important part of Vue, the detection of data changes after the view of the important link. In the $watch usage example in vue.js, we discussed how to implement the basic watch.
Next, let's look at how to implement array change detection.
Example:
Create VM let
vm = new Vue ({
data: {
A: [{}, {}, {}]
}
})
//Key path
vm. $watch (' A ', function () {
//do something
})
Ideas
In JS, it is easy to implement hooks, such as:
Hook a console. Log let
_log = console.log
console.log = function (data) {
//does someting
_log.call (this, data)
}
As long as we implement the custom function, we can observe the array changes.
This function is used in vue.js to Object.create()
implement the custom function to observe the array.
Simply introduce
var a = new object ();//Create an object with no parent
var B = object.create (a.prototype);//b inherits the prototype of a.
Inherited
The array.js definition is as follows:
/get prototype CONST ARRAYPROTO = array.prototype//Create new Prototype object Export Const Arraymethods = object.c Reate (Arrayproto)//implement these functions for the new prototype [' Push ', ' pop ', ' shift ', ' unshift ', ' splice ', ' sort ', ' reverse ']. ForEach (functio N (method) {//Get new prototype function (not implemented undefined at this time) const ORIGINAL = Arrayproto[method]//Add function implementation Object.defineproperty to new prototype (array Methods, method, {value:function mutator () {Let i = arguments.length//get parameter const args = new Array (i) while ( i--) {Args[i] = arguments[i]}//implementation function Const RESULT = original.apply (this, args)//get observer const OB = This.__o B__//Whether to change the array itself let inserted switch (method) {case ' push ': inserted = args break case ' unshift ': inser Ted = args break case ' splice ': inserted = Args.slice (2) Break}//Watch new array inserted && Ob.observea
Rray (inserted)//Trigger update ob.dep.notify () return result}, Enumerable:true, Writable:true, configurable:true}) })
OK, we've defined the Array.js and exported it as a module, modifying Observer
the implementation:
The Export function Observer (value) {
THIS.DEP = new dep ()
this.value = value
//If the array changes its prototype to the
if (Array.isa Rray (value)) {
value.__proto__ = arraymethods
this.observearray (value)
} else {
This.walk (value)
}
}
Observation data element
Observer.prototype.observeArray = function (items) {
for (Let i = 0, L = items.length; i < L; i++) {
observe (Items[i])
}
}
Observer
After the modification, we'll look at Watcher
it and just change its update
function.
Watcher.prototype.update = function (DEP) {
console.log (' 2.update ')
const VALUE = this.get ()
const OldValue = this.value
this.value = value
if (value!== this.value | | value!== NULL) {
This.cb.call (THIS.VM , value, OldValue)
//If there is no this function, it will cause the $watch callback function to be called repeatedly.
//Reason: The array has mutated and the new array is also observed and should be removed from the old observer
Dep.subs.shift ()
}
Results:
Const VM = new Vue ({
data: {
B: [{A: ' A '}, {b: ' B '}]
}
)
vm. $watch (' B ', (val) => {
Console.log ('------I see You now-----')
})
Vm.b.push ({c: ' C '}) Vm.b.pop ({c: ' C '})
Vm.b.push ({c: ' C '})
//Result:
//Console.log ('------ I see you-----')
//Console.log ('------I see you-----')
//Console.log ('------I see you-----')
Summarize
So far, we have implemented the detection of array changes. The Object.create () function is mainly used. Hope that the content of this article for everyone's study or work can bring certain help, if there is doubt you can message exchange.