Based on
Li Yongning's homepage (juejin.cn) Learn and summarize the tutorial.
When initializing new Vue({}), first call the Vue. Prototype. _initmethod defined in initMixin through the Vue constructor in (src/core.instance/index.js).
Vue constructor:
//Vue constructor function Vue (options) { if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue) ) { warn('Vue is a constructor and should be called with the `new` keyword') } //Call Vue prototype._ Init method, which is defined in initMixin this._init(options) }
Vue. prototype._ The init method gives each Vue instance an id, which is incremented in turn; Start processing component configuration items after: if it is a sub component, perform performance optimization and put some deep-seated attributes on the component configuration object into VM$ Options, Improve code execution efficiency (reduce attribute lookup at runtime); if it is a root component, merge the options, merge the global configuration options into the local configuration of the root component, and call the resolveConstructorOptions method to get the options from the instance constructor first. If there is a base class, get the configuration options in the cached base class, and compare the configuration options of the base class with the cached configuration options. If Make changes, merge the changed options and extend options, and assign the new options to options.
resolveConstructorOptions method code:
//Resolve configuration item from constructor export function resolveConstructorOptions (Ctor: Class<Component>) { //Get options from instance constructor let options = Ctor.options if (Ctor.super) { const superOptions = resolveConstructorOptions(Ctor.super) //Configuration options for caching base classes const cachedSuperOptions = Ctor.superOptions if (superOptions !== cachedSuperOptions) { //If it is inconsistent, the configuration item of the base class has changed // super option changed, // need to resolve new options. Ctor.superOptions = superOptions // check if there are any late-modified/attached options (#4976) const modifiedOptions = resolveModifiedOptions(Ctor) // update base extend options if (modifiedOptions) { //The base class has changed. Merge the changed option with the extend option, and assign the new option to options extend(Ctor.extendOptions, modifiedOptions) } options = Ctor.options = mergeOptions(superOptions, Ctor.extendOptions) if (options.name) { options.components[options.name] = Ctor } } } return options }
The most important part of initialization after processing component configuration items.
1.
Initialization of initLifecycle(vm) component relationship attributes, such as $parent $children $root $ref, etc.
2.
initEvents(vm) initializes custom events.
3.
initRender(vm) initializes the slot and gets this$ Slots, define this_ C is the createElement method (h function).
4.
callHook(vm, 'beforeCreate') executes the beforeCreate declaration cycle function.
5.
initInjections(vm) initializes the inject option, obtains the configuration object with result[key] = val shape value, and performs response processing. (not used for general development)
Initiations method code:
/** * Parse the inject option to get a configuration object in the form of {key:val} * Respond to the analysis results */ export function initInjections (vm: Component) { //Parse the inject option from the configuration item, and finally get the result[key] = val const result = resolveInject(vm.$options.inject, vm) if (result) { toggleObserving(false) Object.keys(result).forEach(key => { /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { defineReactive(vm, key, result[key], () => { warn( `Avoid mutating an injected value directly since the changes will be ` + `overwritten whenever the provided component re-renders. ` + `injection being mutated: "${key}"`, vm ) }) } else { //The parsing results are processed in response, and each key is proxy to the vue instance //this.key defineReactive(vm, key, result[key]) } }) toggleObserving(true) } } /** * * @param inject ={ * key:{ * from: provideKey, * default: xx * } * } * @param vm * @returns {key:val} */ export function resolveInject (inject: any, vm: Component): ?Object { if (inject) { // inject is :any because flow is not smart enough to figure out cached const result = Object.create(null) const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject) //Traverse the array of key s in the reject option for (let i = 0; i < keys.length; i++) { const key = keys[i] // #6574 in case the inject object is observed... if (key === '__ob__') continue //Get from attribute const provideKey = inject[key].from //Find the provide option from the configuration item of the ancestral component to find the value of the corresponding key let source = vm while (source) { if (source._provided && hasOwn(source._provided, provideKey)) { // result[key] = val result[key] = source._provided[provideKey] break } source = source.$parent } if (!source) { // Set defaults if ('default' in inject[key]) { const provideDefault = inject[key].default result[key] = typeof provideDefault === 'function' ? provideDefault.call(vm) : provideDefault } else if (process.env.NODE_ENV !== 'production') { warn(`Injection "${key}" not found`, vm) } } } return result } }
6.
initState(vm) is the core of the responsive principle and handles props, meehods, computed, data, watch and other options.
7.
initProvide(vm) handles the provide option.
8.
callHook(vm, 'created') calls the created declaration cycle hook function.
Finally, if there is an el option on the configuration item, the $mount method will be called automatically. If there is no el option, it needs to be called manually after initialization$ mount.
Enter the mount state after all execution.
*Literacy:
Option merging occurs in three places
1.Vue. Component (compname, COMP) is merged with options. The built-in global components of Vue and the global components registered by the user are merged and finally placed in the global component option.
2. {component: {xxx}} is locally registered. When executing the render function generated by the compiler, options are merged to merge the global configuration items into the local configuration items of the component.
3. When initializing the root component, merge the global configuration options into the local configuration of the root component.
<comp @click="handleclick"></comp>
The monitoring of events on a component is the monitoring of the sub component itself, that is, who triggers who monitors. Finally compiled into this$ emit{ 'click' }, this.$ On {'click', function handleclick() {}}