Reactivity responsive
1. object.defineProperty
Disadvantages and vue2.0 hacks
let vm = new Vue({
data() { a: 1 }
})
Copy the code
If the data level is too high and you need to recursively resolve the attributes in the object, add set and GET methods in turn
1.1 New Properties Cannot be Set
Normally, the data being listened on is already listened on at initialization. Subsequent new attributes cannot be listened on and have to be handled via vm.$set.
This.$set(target, key, value).
Document address: cn.vuejs.org/v2/api/#Vue…
1.2 Array listening failed
Vue2 hijacks all array prototype methods to listen on arrays
Let oldArrayMethods = array. prototype export const arrayMethods = object. create(oldArrayMethods) arrayMethods.__proto__ = oldArrayMethods const methods = [ 'push', 'shift', 'unshift', 'pop', 'sort', 'splice', 'reverse' ] methods.forEach(method=>{ arrayMethods[method] = function (... args) { const result = oldArrayMethods[method].apply(this, Let inserted // Current user inserted element let ob = this.__ob__ switch (method) {case 'push': case 'unshift': inserted = args break case 'splice': Splice (0,1,{name:1}) inserted = args.slice(2) default: Break} if(inserted) ob.observerarray (inserted) // Continue to observe the new attribute return result}})Copy the code
Proxy — reactive
Object. DefineProperty is the method supported by IE 8, as opposed to Proxy. Vue3 supports Internet Explorer 11 at least.
In the previous article, we looked at the use of defineProperty and Proxy.
When we write defineProperty, we always loop through the attributes of the object with a layer of objects, adjusting the changes one by one:
Object.keys(data).forEach(key => { Object.defineProperty(data, key, { get() { return data[key] }, Set (value) {// key = value}})})Copy the code
The Proxy listens on an object like this:
new Proxy(data, { get(key) { }, set(key, value) { },});
Copy the code
You can see that the syntax of Proxy is very simple, and it does not need to care about the specific key. What it intercepts is “modify any key on data” and “read any key on data”. So, whether the existing key or the new key, can listen.
Proxies are also more powerful in that they can intercept more operators than just get and set. Proxy has up to 13 intercepting methods, not limited to apply, ownKeys, deleteProperty, has, and so on that Object. DefineProperty does not have.
Vu3 responsive simplified version
Especially large simplified version of mini-vue online code
The core principle of reactive mode is publish-subscribe + Proxy mode. Vue3 uses Proxy to reconstruct the whole reactive code. The following is a simplified version of Proxy code
let activeEffect class Dep { subscribers = new Set() _value constructor (value) { this._value = value } get value () { This.depend () return this._value} set value (value) {this._value = value} // Depend () {if (activeEffect) { This.subscribers. Add (activeEffect)}} notify () {this.subscribers. ForEach (effect => {effect()})} WatchEffect function watchEffect (effect) {activeEffect = effect // If the function has a reactive object, ActiveEffect = null} // proxy version // Const reactiveHandlers = {get(target, key) {const value = getDep(target, Value if (value && typeof value === 'object') {return reactive(value)} else {// The basic data type is returned directly Return value}}, set(target, key, value) {// Call getDep(target, key, value); Key).value = value}} const targetToHashMap = new WeakMap() // Vue3 is used where the data, and then make the data responsive. Function getDep (target, key) {let depMap = targetTohashmap. get(target) if (! depMap) { depMap = new Map() targetToHashMap.set(target, depMap) } let dep = depMap.get(key) if (! dep) { dep = new Dep(target[key]) depMap.set(key, Reactive function reactive(obj) {return new Proxy(obj, reactiveHandlers)}Copy the code
// reactive defines the object {count: 0}, which is passed to the Proxy target const state = reactive({count: 0}) // assigns the value to actibveEffect and executes the method immediately. // 1, state. Count read get // 2, call getDep, target is {count: 0},key is count // 3, create object weakMap: {count:0} : new Map({count: New Dep(0)}) // getDep(target, key).value getDep(target, key).value WatchEffect (() => {console.log(state.count)}) // 0 // change the value of state.count // (1) Proxy intercepts SET and now subscribers are given a call to getDep (0). When deP new DEp (0) is obtained, its value genus is modified and setter // notify is triggered. Console. log() => console.log(state. Count) // Return value 1 state.count++ // 1Copy the code
Reference:
The principle of reactive implementation