What this article brings to you is about the principle of the Vue response. Vue response to the principle of analysis, there is a certain reference value, the need for friends can refer to, I hope to help you.
Initstate
New Vue () = _init () = Initstate:
function Initstate (vm:component) { vm._watchers = [] const OPTS = vm. $options if (opts.props) initprops (VM, Opts.props) if (opts.methods) initmethods (VM, Opts.methods) if (opts.data) { initdata (VM) } else { Observe (Vm._data = {}, True/* asrootdata */) } if (opts.computed) initcomputed (VM, opts.computed) if (opts.watch && opts.watch!== nativewatch) { Initwatch (VM, Opts.watch) }}
Determine if the Vue instance exists props, methods, data, computed, watch to invoke the corresponding initialization function
Initprops and InitData
The main task is to call DefineProperty to mount a Get for the property (when the hook is triggered, the DEP instance of the current property is pushed into the current dep.target, which is the dependency of the current watcher deps that it subscribes to, dep.target the following. The DEP instance also pushes the current watcher, the observer into its subs array, and the Set method (notifies all observers in the dependency subs watcher to call their Update method).
initcomputed
Its role is to traverse all the attributes in the computed object and give the property new a computed watcher (a DEP dependency is defined in the computed attribute to the watcher subscription that needs to use the computed property). The Get (Get method) is also mounted by calling DefineProperty to the computed, and the Set method (set method will determine if it is passed in, if not passed to the noop null function)
The Get method of the computed property is the return value function of the following function
function Createcomputedgetter (key) { return function Computedgetter () { Const Watcher = this._computedwatchers && This._computedwatchers[key] if (watcher) { watcher.depend () return watcher.evaluate () } }}
Note the Watcher.depend (), which allows the Watcher observer with the attribute to subscribe to the dependency in the Watcher, and the computed property watcher pushes the watcher that subscribes to it into his subs (when the value of the computed property changes, Notification subscription to his watcher observer)
Watcher.evaluate (), the method is called by the Get method of the Watcher ( It is important to note that the Watcher get method calls Pushtarget to put the previous Dep.target instance into the stack, and sets Dep.target as the computed watcher, the response property that is dependent on the computed property will be computed Watcher pushes into its subs, so when the dependent response property changes, the subscription to his computed watcher,computed watcher is notified and the Watcher calling the Update method to subscribe to the computed property is notified. The Get method evaluates the value by calling the handler function that evaluates the property key binding.
Initwatch
The Watcher is User watcher, which the developer himself customizes in the component.
The Initwatch function is to iterate through the attributes in watch and call the defined $watch for each watch listener's properties.
Vue.prototype. $watch = function ( exporfn:string | function, cb:any, options?: Object ): function { const VM:COMPONENT = this if (Isplainobject (CB)) { return Createwatcher (VM, EXPORFN, CB, Options) } options = Options | | {} Options.user = True//Represents the watcher is user-defined watcher Const Watcher = new Watcher (VM, EXPORFN, CB, options) if (options.immediate) { cb.call (VM, Watcher.value) } return function Unwatchfn () { Watcher.teardown () } }
When calling new watcher in the code, as with render Watcher, execute the Watcher get method, call Pushtarget to assign the current user watcher to Dep.target,get () in value = This.getter.call (VM, VM) This statement triggers the GET method of the response property of the custom watcher listener and pushes the current user watcher into the subs of the property dependency, so when the user After the Watcher listener's property set is triggered, the notification subscribes to the dependent watcher to trigger the update, which is the corresponding handler of the key that triggered the watch binding. The poptarget is then called to the stack and assigned to Dep.target.
$mount
Initstate initialization work is roughly here, and then execution $mount start rendering work.
$mount main work: New has a render watcher and passes Updatecompent as callback in and executes
Updatecomponent = () = { vm._update (Vm._render (), hydrating) }new Watcher (VM, Updatecomponent, NoOp, { Before () { if (vm._ismounted) { callhook (VM, ' BeforeUpdate ')}}} , True/* isrenderwatcher */)
When new Watcher is in three watcher, only computed watcher does not execute its get () method from the beginning. $mount this render watcher in new will call the Get () method and call Pushtarget to assign the current render watcher to Dep.target. Next the play comes, call Updatecomponent, the method executes Vm._update (Vm._render (), hydrating), where the render function triggers the get hook of the response property used in the HTML. The get hook causes the dependent instance dep of the responsive property to push the current render watcher into its subs array, so when the dependent response property changes, it iterates through the watcher of the subs notification subscription to it to invoke update ().
Example
Maybe everyone to watcher and DEP to transfer to confused, I tell an example
<div id= "App" > <div>{{a}}</div> <div>{{b}}</div> </div>new Vue ({ el: "#app", data () { return { a:1, } }, computed:{ B () { return a+1 } },})
I speak directly from the rendering, only with DEP and watcher.
$mount: New A Render Watcher (watcher in the Get method assigns the render watcher to Dep.target) will trigger Vm._update (Vm._render (), hydrating), Render will get the response attribute used in HTML, the above example uses a, this will trigger A's get hook, where dep.depend () pushes the current render watcher into the subs array of DEP for the A property.
Then continue execution, access to B (b is the value of the computed property), which triggers the GET method of the computed property. The Get method of the computed property is the return function after the call to the Createcomputedgetter function Computedgetter,computedgetter function watcher.depend () is executed. The depend method of Watcher is reserved for computed watcher use.
I just said it above. Besides computed watcher, the other two watcher will execute their get method after new, so computed watcher after new is done, it will be new Dep.
Go back to the method that was just said to be computed watcher Watcher.depend (), his role is to perform this.dep.depend () (Computed watcher definition of DEP is used here). This.dep.depend () causes the current render watcher to subscribe to the computed property dependency, and the computed property pushes the render watcher into its own subs ([Render Watcher]). When the value of the computed property is modified, the Watcher in subs is notified to call Update (), so the computed property value changes to the page refresh.
Back to the get hook that triggered the B calculation property, the Get Hook will execute Watcher.evaluate (), and Watcher.evaluate () will execute the computed watcher get () method.
At this point, the Dep.target (render watcher) is pushed into the targetstack stack (after it is deposited for later removal), and the computed watcher of the computed attribute is assigned to Dep.target. The Get method in value = This.getter.call (VM, VM) executes the handler of the computed property binding.
As in the example above, return a + 1. Using a then it is bound to trigger a get hook, the get hook will call Dep.depend (), Dep.depend () will let computed watcher will be DEP in its deps array, a DEP will be the current dep.target ( Computed watcher) into its subs array, the current example of a in the subs will be [render watcher,computed watcher], so a value change will traverse the subs in a watcher call the update () method , the use of a in the HTML will refresh, the computed property watcher call the update () method will notify his own subs ([Render Watcher]) in the render watcher to call the Update method, The computed attribute B used in HTML does not refresh the DOM (this is a wake-up, I'm just saying, the calculation of property dependent property changes after he does not necessarily trigger the update, he will compare the value of the calculation after the change).
The Get () method of the computed watcher will finally call Poptarget (), which will then be stored in the render watcher stack and assigned to Dep.target, when my example targetstack becomes an empty array.
The Get method of the render watcher will be executed at the end of the stack, and the Dep.target assignment will be empty.