preface
Through the previous chapter, we know the Vue initialization data response principle, only shared how the object through defineReactive method to create monitoring data attributes, and the array is just slightly over, below we through the source code to get a look
Did not see the previous chapter Vue responsive principle, no matter, come, walk a wave of small gifts up Go Vue Object defineProperty
Observer Array section
First look back to the Observer class constructor SRC/core/Observer/index, js
// Let's go back to this code
if (Array.isArray(value)) { / / array
if (hasProto) {
protoAugment(value, arrayMethods) // Rewrite the array prototype method
} else {
copyAugment(value, arrayMethods, arrayKeys) // Copy the existing methods of the array
}
this.observeArray(value) // Look deeply at each item in the array
} else {
this.walk(value) // If it is an object, redefine the object type data (described in the previous chapter).}}Copy the code
protoAugment
The protoAugment method overwrites the array prototype method and points the prototype rewrite to arrayMethods
function protoAugment (target, src: Object) {
target.__proto__ = src
}
Copy the code
observeArray
The observeArray method iterates through the array and calls an observer to see if it has been listened on. If it has not been listened on, the new Observer class creates a listener, as described earlier
// If it is an array, iterate over the array and go to the observer method to see if it is listening
observeArray (items: Array<any>) {
for (let i = 0, l = items.length; i < l; i++) {
observe(items[i]) // Observe each item in the array}}Copy the code
Implement the array listener core
The js file content is not much, mainly to do a few things the SRC/core/observer/array. Js
- Create array prototype, assign to
arrayMethods
- Override the array prototype method to
arrayMethods
And modify this - The method entity looks up 10 rows as it recursively iterates over the changed array data
observeArray
- Notifying Wachter to update the view
import { def } from '.. /util/index'
const arrayProto = Array.prototype
// Create an array prototype and assign it to arrayMethods
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [ // The array is often modified
'push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse'
]
/** * Intercept mutating methods and emit events */
methodsToPatch.forEach(function (method) {
// cache original method
const original = arrayProto[method]
// Rewrite the array prototype
def(arrayMethods, method, function mutator (. args) {
const result = original.apply(this, args) / / change this
const ob = this.__ob__
let inserted
switch (method) {
case 'push':
case 'unshift':
inserted = args
break
case 'splice':
inserted = args.slice(2)
break
}
// Observe the newly inserted data again
if (inserted) ob.observeArray(inserted)
// Notify view updates
ob.dep.notify()
return result
})
})
Copy the code
conclusion
Vue rewrites the prototype chain by hijacking the array in data. Points to the array prototype method you define so that you can notify dependencies of updates when the array API is called. If the array contains a reference type; Reference types in the array are monitored again.
A link to the
- Front-end visualization platform implementation scheme
- Vue3 10 minutes takes you seconds to vue3
- Vue template compilation principle
- The vue constructor extends
- How does VUEX state management work
- Vue-router source analysis principle
- Vue [how to listen for array changes]
- Handwritten Vue response [object.defineProperty]
- Vue responsive source sharing