SoFunction
Updated on 2025-04-05

Detailed explanation of the initState state initialization in Vue 2

initState state initialization

After the configuration standardized merge and declaration cycle initialization is completed, thecallHook('beforeCreate')To indicate that the component has entered the official instantiation stage.

At this time, the corresponding processing of configuration items such as data, methods, listeners, etc. will be performed, and a series of verifications will be performed in the development environment to throw verification exception information. The entire data initialization process isinitInjection => initState => initProvide,butinjection/provideIt is usually used together, so here is the order and the two are placed later to analyze together.

First, the function definition of initState:

 export function initState(vm: Component) {
   const opts = vm.$options
   if () initProps(vm, )

   // Composition API
   initSetup(vm)

   if () initMethods(vm, )
   if () {
     initData(vm)
   } else {
     const ob = observe((vm._data = {}))
     ob && ++
   }
   if () initComputed(vm, )
   if ( &&  !== nativeWatch) {
     initWatch(vm, )
   }
 }

The whole process is actually very clear:

  • initProps: InitializationpropsComponent parameter configuration
  • initSetup: AnalysissetupConfiguration, processingsetupThe return value of   (here is mainly the content added after version 2.7 to adapt to the v3 syntax)
  • initMethods: Initialize component method
  • initData: Initialize variables in the component
  • initComputed: Initialize component calculation properties
  • initWatch: Initialize the internal listener of the component

1. initProps

The function is defined as follows:

 function initProps(vm: Component, propsOptions: Object) {
   const propsData = vm.$ || {}
   const props = (vm._props = shallowReactive({}))
   const keys: string[] = (vm.$options._propKeys = [])
   const isRoot = !vm.$parent
   
   if (!isRoot) {
     toggleObserving(false)
   }
   for (const key in propsOptions) {
     (key)
     const value = validateProp(key, propsOptions, propsData, vm)
     if (__DEV__) {
       const hyphenatedKey = hyphenate(key)
       if (isReservedAttribute(hyphenatedKey) || (hyphenatedKey)) {
         warn('')
       }
       defineReactive(props, key, value, () => {
         if (!isRoot && !isUpdatingChildComponent) {
           warn('')
         }
       })
     } else {
       defineReactive(props, key, value)
     }
     if (!(key in vm)) {
       proxy(vm, `_props`, key)
     }
   }
   toggleObserving(true)
 }

This process will traverse the entire componentpropsConfiguration items (after mergeOptions, inheritance and mixin have been included), and eachprop keyConvert from camel form to-The form of short horizontal lines connection.

This is why the official recommendationpropsConfiguration and useLower case camel, and when the component is used, the binding parameters are used- Short horizontal lineThe reason.

After that, eachpropofkeyWhether it complies with the specifications (that is, it is not Vue's built-in keywords ref, key, etc., or it is not in the configuration.isReservedAttr(key)Prohibited attribute name); finally, bydefineReactiveCome on rightpropPerform responsive processing and mount it tovm._propsmiddle.

Of course, the above responsive processingFor root components only, if it is not the root component, it will be called in the front part of the function.toggleObserving(false)To turn off responsive processing

2. initSetup

This part is to adapt to the new part of the v3 syntax. I won’t put the source code here, just briefly introduce it.

This method is located in the src/v3/ file. During the execution process, there are mainly the following steps:

  • passcreateSetupContext(vm)Create onesetupThe context object during function execution, which includesattrs,listeners,slots,emitSeveral attributes, and oneexposeMethod; then bind this context object to the component's_setupContextOn the attribute, last callsetCurrentInstanceSpecify the current context instance as the current component instancevm
  • CallpushTarget()Block the process of dependency collection and callinvokeWithErrorHandlingCome and getsetupThe return value of the function
  • Then deletesetupThe current instance context in  , callpopTargetRecovery dependency collection
  • judgesetupThe execution return value of the function. If it is a function, it means that the returned isrender, assign the return value tooptionsUsed for later executionmountRender; if it is an object, the return value will be assigned tovm._setupState, then iterate through the return value object and perform responsive processing

3. initMethods

The function definition is as follows:

 function initMethods(vm: Component, methods: Object) {
   const props = vm.$
   for (const key in methods) {
     if (__DEV__) {
       if (typeof methods[key] !== 'function') {
         warn('')
       }
       if (props && hasOwn(props, key)) {
         warn('')
       }
       if (key in vm && isReserved(key)) {
         warn('')
       }
     }
     vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm)
   }
 }

This part is very simple, just byFunctions to change component configurationoptionsThe this pointer of each method in  and finally rebind to the current component.

The verification here is actually to check whether the name will conflict with the built-in method name of js, or there is a method with the same name in props.

4. initData

ExecutioninitDataBefore, it will be verifiedoptionsIf there is any data configuration in it, it will be initialized as an empty object.

Its function definition is as follows:

 function initData(vm: Component) {
   let data: any = vm.$
   data = vm._data = isFunction(data) ? getData(data, vm) : data || {}
   if (!isPlainObject(data)) {
     data = {}
     __DEV__ && warn('')
   }
   const keys = (data)
   const props = vm.$
   const methods = vm.$
   let i = 
   while (i--) {
     const key = keys[i]
     if (__DEV__) {
       if (methods && hasOwn(methods, key)) {
         warn('')
       }
     }
     if (props && hasOwn(props, key)) {
       __DEV__ && warn()
     } else if (!isReserved(key)) {
       proxy(vm, `_data`, key)
     }
   }
   const ob = observe(data)
   ob && ++
 }

This is actually quite simple, which is to verify whether there is data with the same name as props or methods and proxy it tovm._dataUp, finally passedobserveMethods responsively process the data.

5. initComputed and initWatch

These two parts are mainly configureddataandpropsThe variables ofChange detection (listening), because it involves the responsive system of VueWatcherObserver definition and dependency collection system have a lot of content in the overall content, so I will talk about it in the whole picture in the following.

A brief analysis of the basic logic of both:

initComputed:

  • Getfor each computed attribute defined ingetMethod asgetter(If it is a function, then this function is directly used as a getter)
  • If the key of the calculated attributeCannot be found on the current instance, then pass directlydefineComputedDefine a computed attribute
  • If it can be found, then determine whether it is indata,methods,propsand a corresponding error is reported

initWatch:

This process is simpler because there is no need to verify the repetition of the key, so it will be traversed directly., If the listener of a certain attribute has two handler methods, the method will be proposed and finally calledcreateWatcherTo create a listener.

This is the end of this article about the detailed explanation of the initState status initialization in Vue 2. For more related Vue initState content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!