According to the Demo configuration, run the demo, then ignore the branch story, just analyze the main flow of Vue running.
Introduce Vue and App
To execute index.js, run:
import Vue from 'vue';
import App from './app.vue';
Copy the code
- variable
Vue
为Vue
Constructor, in executionVue
The file will be initialized during the processVue
The prototype variable method of,Watch
Class,Dep
Class and so on. - variable
App
For afterwebpack
Compile, passVue-loader, VUe-template-compiler, VueLoaderPlugin
Inclusion after actionrender
和staticRenderFns
的Component option object
:
{
name: "app"Data: ƒ data() components: {Child: {... }} props: {num: ƒ.nameƒ} beforeCreate: ƒ beforeCreate() created: ƒ created() beforeMount: ƒ beforeMount() Mounted: ƒ Mounted () : ƒ beforeUpdate() updated: ƒ updated() ƒ : ƒ ()true
__file: "src/app.vue"
}
Copy the code
Where staticRenderFns contains an array of render functions generated separately by vNode marked as static nodes.
To deal withvm.$options
Execute new Vue(), that is, execute _init on the Vue prototype chain, internally execute:
if (options && options._isComponent) {
initInternalComponent(vm, options);
} else {
vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options || {}, vm);
}
Copy the code
Execute different methods depending on whether the passed options contain the component identifier.
initInternalComponent
If it is a component call, execute initInternalComponent to set vm.$options.
In the case of the first App component, the options method assigns the component’s options to the vm.$options prototype. $options = vm.$options = vm.
{
parent: Vue {_uid: 0._isVue: true.$options: {... },_renderProxy: Proxy._self: the Vue,... }// Parent component instance
_parentVnode: VNode {tag: "vue-component-1-app".data: {... },children: undefined.text: undefined.elm: undefined,... }/ / component vnode
propsData: {title: 1.name: "one"} // Props on component vNode
_parentListeners: {welcome: ƒ} // Events on component vNode
_renderChildren: undefined / / slots vnode
_componentTag: "app" // Component vNode component instance name
}
Copy the code
The prototype is the options property (defined in vue.extend as the component options object after mergeOptions) mounted under the child component constructor.
resolveConstructorOptions
If it is not a component resolveConstructorOptions and mergeOptions Settings vm. $options.
The Ctor argument is the passed vm.constructor, or Vue constructor. Options is vue. options, which is defined in the initGlobalAPI method. Ctor.options for this demo are:
{
components: {KeepAlive: {... },Transition: {... },TransitionGroup: {... }} directives: {model: {... },show: {... }} filters: {} _base: ƒ Vue(options)}Copy the code
Ctor. Options: Ctor. Options: Ctor. ExtendOptions recursively merges Ctor. ExtendOptions with its parent constructor’s options, and returns the merged options.
mergeOptions
Check whether the options.components name is valid by executing the checkComponents method on the child (options). Then according to the options configuration, then check and format the Props, Inject, and Directives. MergeOptions is then recursively called to merge extends and mixins based on whether they exist.
Call mergeField to the parent (resolveConstructorOptions (vm) constructor)) and child (options) the strats processing. Strats is used to merge processing options. After merging, data is mergedInstanceDataFn. Finally, assign options to the instance $options property. Get the vm. $options:
{
components: {App: {... },Bppƒ} cache: {} filters: {} _base: ƒ Vue(options) EL:"#main"Data: ƒ mergedInstanceDataFn() computed: {computeƒ} the methods: {plus: ƒ.hideƒ} watch: {b: {... ƒ}} beforeCreate: [ƒ] Created: ƒ] beforeMount: ƒ]Copy the code
Initialize the
Then execute:
initProxy(vm);
/ /...
initLifecycle(vm);
initEvents(vm);
initRender(vm);
Copy the code
The initialization contents are analyzed as follows:
initProxy
Renderproxy = new Proxy(VM, Handlers); Handlers are hasHandler.
Handlers are getHandler if options has render and _withStripped is true.
initLifecycle
$parent, $root, $children, _watcher, _isMounted;
$parent, $root, $child, $child, $child, $child, $child, $child
If parent-options. abstract is true, update $parent of the keep-alive component to the parent of the keep-alive component.
initEvents
If it is a child component, check whether $options._parentListeners are events on the component Vnode. If so, execute vm.$on to listen for custom events on the current sub-component instance, which are triggered by VM.$emit.
$ON, $EMIT is essentially a publish subscription. The $ON collection subscription is mounted under the _events property of the instance and $EMIT executes a list of subscribe events.
initRender
Initialize render related functions _c, $createElement, etc., and then listen on the instance:
$attrs
Contains non-action in parent scopeprop
Feature bindings identified (and retrieved)$listeners
Contains the parent scope.native
Modifier of)v-on
Event listener)
Here are two attributes (each new a LIST of Dep subscribers).
If it is a child component, _parentVnode is assigned to vm.$vnode.
If there are regular slots, named slots, scopedSlots, etc., then initialize $slots, $scopedSlots.
Triggers the beforeCreate hook
callHook(vm, 'beforeCreate');
Copy the code
Execute the lifecycle hook beforeCreate and print vue beforeCreate.
The summary of this chapter
- This chapter introduces
vue
performbeforeCreate
Stage; - Merge handles components
options
The parent componentoptions
Platform initializationoptions
,vm.$options
; - Initialization is lifecycle specific
Vue
Various properties of instances, such as parent-child relationships$parent
Initialization, etcevent
Event delivery related; - Initialize the render related
Vue
Functions on instances, slots, etc.