Peruse the Vue2.6.14 Core source code (6): define Active
/** @date 2021-09-12 @description read Vue2.6.14 Core source code (6): defineReactive */Copy the code
One (sequence)
This chapter focuses on the reactive nature of Vue, implemented by calling Define Active.
Two (defineReactive)
export function defineReactive ( obj: Object, key: string, val: any, customSetter? :? Function, shallow? : Boolean) {// declare dep, Every statement in response to a type of value has an own dep const dep = new dep () / / retrieve attributes descriptor const property = Object. GetOwnPropertyDescriptor (obj, If (new && property.64x === false) {return} // Handle for any additional control system that works without any additional control system Pre-defined getter/setters // Get getters and setters const getter = property && property.get const setter = property && Set // In this case, assign the value val if ((! Getter | | setter) && the arguments. Length = = = 2) {val = obj} [key] / / / / observer for the object of value, // If defineReactive is called in the observer, this is equivalent to recursive processing. If defineReactive is called in the observer, Another object, DefineReactive => observe => new Observer() => observer.walk() => defineReactive => observe... // Let childOb =! Let childOb =! Shallow && observe (val). / / the Object set defineProperty getter and setter Object. DefineProperty (obj, key, {enumerable: true, configurable: true, // getter get: Function reactiveGetter () {// Get value const value = getter? Getter. call(obj) : Val // pushTarget assigns dep. target (null initially, // The popTarget function can be used to remove the current dep. target // Ensure that only one watcher is processed at the same time // The watcher is called when the component's watcher is declared. Push the current watcher into targetStack, And dep.target = watcher if (dep.target) {// Collection depends on dep.depend() if (childOb) {// Collection depends on childob.dep.depend () if DependArray (value)}}} return value}, set: (array.isarray (value)) {$dependArray(value)}} return value}, set: Function reactiveSetter (newVal) {// Get the current value const value = getter? Getter. call(obj) : Val / * eslint - disable no - self - compare * / / / value did not change, or for the NaN if (newVal = = = value | | (newVal! == newVal && value ! == value)) { return } /* eslint-enable no-self-compare */ if (process.env.NODE_ENV ! == 'production' && customSetter) { customSetter() } // #7981: for accessor properties without setter if (getter && ! Setter) return if (setter) {setter.call(obj, newVal)} else {val = newVal} Shallow && observe(newVal) // Notify all dependencies dep.notify()}})}Copy the code
3 (observe)
export function observe (value: any, asRootData: ? Boolean) : the Observer | void {/ / not object or is VNode return the if (! isObject(value) || value instanceof VNode) { return } let ob: The Observer | void / / have been observed, __b__ if (hasOwn(value, __ob__ instanceof Observer) {ob = value.__ob__} else if (shouldObserve && // need to be observed! IsServerRendering () && / / not server side rendering (Array. IsArray (value) | | isPlainObject (value)) && / / value is an Array or object Object. IsExtensible (value) && // whether the current value isExtensible! Value._isvue // Not Vue instance) {// Create a new Observer ob = new Observer(value)} if (asRootData && ob) {ob.vmcount+ +} return ob}Copy the code
Boss (Observer)
export class Observer { value: any; dep: Dep; vmCount: number; // number of vms that have this object as root $data constructor (value: Any) {this.value = value this.dep = new dep () this.vmCount = 0 // def(value, '__ob__', This) // value isArray if (array.isarray (value)) {// the object in the current environment has a __proto__ attribute if (hasProto) {protoAugment(value, ArrayMethods)} else {copyAugment(value, arrayMethods, arrayKeys)} ObserveArray (value)} else {// call walk this.walk(value)}} /** * walk through all properties and convert them into * getter/setters. This method should only be called when * value type is Object. */ walk (obj: Object) { const keys = Object.keys(obj) for (let i = 0; i < keys.length; DefineReactive (obj, keys[I])}} /** * Observe a list of items. */ observeArray (items: Array<any>) { for (let i = 0, l = items.length; i < l; i++) { observe(items[i]) } } }Copy the code
Wu (Dep)
export default class Dep { static target: ? Watcher; id: number; subs: Array<Watcher>; constructor () { this.id = uid++ this.subs = [] } addSub (sub: Watcher) { this.subs.push(sub) } removeSub (sub: Watcher) { remove(this.subs, sub) } depend () { if (Dep.target) { Dep.target.addDep(this) } } notify () { // stabilize the subscriber list first const subs = this.subs.slice() if (process.env.NODE_ENV ! == 'production' && ! config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they Fire in correct // order subs.sort((a, b) => a.id -b.id)} // Update for (let I = 0, l = subs.length; i < l; i++) { subs[i].update() } } }Copy the code
Final (navigation)
Read Vue2.6.14 Core source code (1): entry
Read Vue2.6.14 Core source code (2): After Vue
Read Vue2.6.14 Core source code (3): initGlobalAPI
Read Vue2.6.14 Core source code (4): _init
Read Vue2.6.14 Core source code (5): initState
Peruse the Vue2.6.14 Core source code (6): define Active