Vue source analysis [5] – VUE life cycle
The following code and analysis process need to be viewed in conjunction with vue.js source code, by comparing the break points one by one.
1.beforeCreate
Let’s take a look at the execution process
- New Vue is executed first
initMixin(Vue);
“, but only a _init is mounted to the Vue and _init is not executed. - Next, execute
new Vue
HTML or main.js will eventually have this entry after importing Vue filesfunction Vue(options)
- To perform
this._init(options);
And into theinitMixin
In theVue.prototype._init = function (options)
. - perform
callHook(vm, 'beforeCreate');
, triggers the beforeCreate hook function
callHook:
// Triggers the lifecycle hook function
function callHook(
vm, / / the Vue instance
hook // Key of the hook function
) {
// #7573 disable dep collection when invoking lifecycle hooks
// DeP collection is disabled when lifecycle hooks are called
//Dep.target = _target; / / store
pushTarget();
// Get the declared periodic function added to the VM
$option = $option;
var handlers = vm.$options[hook];
if (handlers) { / / array
for (var i = 0, j = handlers.length; i < j; i++) {
try {
// Execute the lifecycle function
/** * For example, in the component's beforeCreate hook, we write the following code: Handlers [I]. Call (VM) executes the code for the beforeCreate hook function. And the this pointer is passed to the VM, which is Vue
debugger
handlers[i].call(vm);
} catch (e) {
handleError(e, vm, (hook + " hook")); }}}/** * if you want to call lifecycle hooks: * <el-select ref="select"@hook:mounted="callback"></el-select>
*/
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook);
}
// push a pushTarget
popTarget();
}
Copy the code
1 pushTarget: _target is empty because no parameter is passed. Add the target of the Dep to the targetStack and update the target of the Dep to the current Watcher object
// Dep is the data dependency corresponding to subscriber Watcher
var Dep = function Dep() {
//uid is initialized to 0, and each Dep has a unique ID
this.id = uid++;
/* subs is used to store Watcher's dependencies */
this.subs = [];
};
Dep.target = null; // Initialize to NULL, and finally update with pushTarget
// Target stack
var targetStack = [];
function pushTarget(_target) {
if (Dep.target) { / / target is a Watcher; Static symbol
targetStack.push(Dep.target);// Centrally manage dep.target
}
Dep.target = _target;// Update to the current passed target
}
Copy the code
popTarget
function popTarget() {
// push a pushTarget
// pop() removes and returns the last element of the array.
Dep.target = targetStack.pop();
}
Copy the code
$option = 2 vm.$option = 2 vm.$option = 2 Moving forward, you can see that initMixin(Vue) has this code:
vm.$options = mergeOptions(
// Parse the options attribute on constructor
resolveConstructorOptions(vm.constructor),
// The options are passed by function Vue(options), i.e. new Vue(), where,
// We will define the related lifecycle and related methods and properties on the component ourselves
options || {},
vm
);
Copy the code
[Figure 1. Execute beforeCreate to print this]
2. created
After executing beforeCreate, create is executed.
Execute at initMixin:
callHook(vm, 'created'); // Trigger the created hook functionCopy the code
3. beforeMount
In mountComponent(){} do:
callHook(vm, 'beforeMount');
Copy the code
It is executed in this order:
- New Vue is executed first
initMixin(Vue);
“, but only a _init is mounted to the Vue and _init is not executed. - Next, execute
new Vue
HTML or main.js will eventually have this entry after importing Vue filesfunction Vue(options)
- To perform
this._init(options);
And into theinitMixin
In theVue.prototype._init = function (options)
. - perform
callHook(vm, 'beforeCreate');
, triggers the beforeCreate hook function - perform
callHook(vm, 'created');
Trigger the created hook function - Performs the last step
vm.$mount(vm.$options.el);
Execute the mount at the end,Vue.prototype.$mount = function()
Generate the render rendering function and the actual DOM - At the end of the function, returns
mount.call( this, el, hydrating)
The mount function in the middle of the file,Vue.prototype.$mount = function()
- Then perform
mountComponent( this, el, hydrating)
, mount components, render pages. - At this point, we can see the actual DOM.
4. mounted
In mountComponent(){} do:
if (vm.$vnode == null) {
vm._isMounted = true;
// Execute the life cycle function Mounted
/ / render the data
callHook(vm, 'mounted');
}
Copy the code
Source to ask questions
1. In which lifecycle do AJAX requests go?
When created, the DOM in the view is not rendered, so the DOM node is directly manipulated and relevant elements cannot be found. In Mounted, the DOM has been rendered and DOM nodes can be directly manipulated. In general, they are placed in mounted to ensure logical uniformity. Since server-side rendering does not have DOM and does not support Mounted methods, it is created in the case of server-side rendering.
2. When do I need to use beforeDestroy?
- It is possible that the $on method is used on the current component and needs to be unbound before the component is destroyed
- Clear self-defined timers
- Unbind the event’s native scroll, mousemove…