1. Every computed attribute generates a corresponding observer (Watcher instance) and the observer has values attributes and GET methods.
The getter function for a computed property is called in the GET method and assigns the returned value to value.
Set the initial values of dirty and lazy to true, and lazy does not get methods immediately (lazy execution), but instead executes them when computed values are read.
function initComputed (vm, computed) { var watchers = vm._computedWatchers = Object.create(null); Var isSSR = isServerRendering(); for (var key in computed) { var userDef = computed[key]; var getter = typeof userDef === 'function' ? userDef : userDef.get; . Which [key] = new Watcher (/ / generates observer (Watcher instance) vm, getter | | it, / / getter will implement it in the observer the get method, ComputedWatcherOptions // {lazy: true} lazy execution, do not execute get method, execute when reading computed attribute values); . defineComputed(vm, key, userDef); . }}Copy the code
2. Add a computed property to the component instance, use get and set to get or set the property value, and redefine the getter function
function defineComputed(target, key, userDef) { var shouldCache = ! isServerRendering(); . SharedPropertyDefinition. Get = shouldCache / / redefine the getter function? createComputedGetter(key) : createGetterInvoker(userDef); . Object.defineProperty(target, key, sharedPropertyDefinition); // Add computed properties to the component instance}Copy the code
The getter function for redefinition
function createComputedGetter(key) { return function computedGetter() { var watcher = this._computedWatchers && this._computedWatchers[key]; If (watcher) {if (watcher. Dirty) {// true, evaluate(); // Set dirty to false} if (dep.target) {watcher.depend(); } return watcher.value; // Return the observer value}}; }Copy the code
3. During the initial rendering of the page, computed property values are read and the redefined getter function is triggered.
Since the observer’s dirty value is true, the get method is called, executing the original getter function.
Data (reactive) data is read in the getter function, and data’s getter method is triggered when the data is read, adding the observer corresponding to the computed property to data’s dependent collector (used to notify of updates when data changes).
After the observer’s get method is executed, the observer’s value is updated and dirty is set to false to indicate that the value is updated. After executing the Observer’s Depend method, the upper observer (this observer contains the page update method, Method that reads computed property values) is also added to the dependency collector of Data in the getter function. (The dependency collector of Data in the getter contains observers for computed, And the observer that contains the page update method (with a computed property invoked), and finally returns the value of the computed observer.
4. When you change the data value dependent on the computed property getter function, the update method of the observer is called sequentially, and the update method of the computed observer is called first, based on the observers collected by the previous dependency. Because lazy is true, The observer’s dirty is set to true, indicating that the data value that the computed property getter depends on has changed, but the observer’s GET method is not called to update the value.
Then call the update method of the observer that contains the page update method. When the page is updated, the value of computed property is read and the redefined getter function is triggered. At this time, because the observer with computed property is dirty is true, call the get method of the observer. Update value and return to finish rendering the page.
5. Initialize the dirty value to true, that is, when a computed property value is first read, it is calculated according to the setter and stored on the observer value, and then set the dirty value to false.
When a computed property value is later read, the dirty value is false, and instead of calling the setter to recalculate the value, the observer’s value, which was the last computed value, is returned directly.
Set dirty to true only when the data on which the computed property setter function depends changes, that is, the setter is called to recalculate the next time a computed property value is read.
That is, when data dependent on a computed property does not change, setter functions are not called to recalculate the value, but to read the last calculated value.