Load the complete Vue entry file (SRC /platform/web/ entry-Runtime-with-compiler.js)
Initialize static member (SRC /core/index.js)
  • src/core/index.js
  • Call initGlobalAPI(Vue) to add static methods to the Vue constructor
    • InitGlobalAPI (Vue) location/SRC/core/global – API/index. Js
      • Initialize the vue.config object
      • Set the keep-alive component
      • Use () is used to register components
      • Register vue.mixin () for mixin
      • Register vue.extend () to return a component constructor based on the passed options
      • Register vue.directive (), Vue.component(), vue.filter ()
export function initGlobalAPI (Vue: GlobalAPI) { ... // Exposed util methods. // NOTE: these are not considered part of the public API - avoid relying on // them unless you are aware of the risk. // These tools are not considered part of the global API unless you are aware of some of the risks, Util = {warn, extend, mergeOptions, DefineReactive} // Static method set/delete/nextTick vue. set = set vue. delete = del vue. nextTick = nextTick... // Initialize the vue. options object, And give its extension / / components/directives/filters Vue. Options = Object. The create (null) ASSET_TYPES. ForEach (type = > {Vue. Options [type + 's'] = Object.create(null) }) // this is used to identify the "base" constructor to extend all plain-object // Components with in Weex's multi-instance scenarios. Vue.options._base = Vue // Sets keep-alive components for this multi-instance scenario extend(Vue.options.components, BuiltInComponents) // Register vue.use () for initUse(Vue) // register vue.mixin () for initMixin(Vue) // register vue.extend () Returns a component's constructor, initExtend(Vue), based on the options passed in. // Register vue.directive (), vue.ponent (), vue.filter () initAssetRegisters(Vue)}Copy the code
  • Load (SRC/platforms/web/runtime/index, js) the file by the extend to the vue global registration instructions (v – model and v – show) and component (Transition and TransitionGroup), Add _patch_ function to Vue prototype to transform virtual DOM into real DOM, and call patch function to judge browser environment
// /src/platforms/web/runtime/index.js

// install platform runtime directives & components
extend(Vue.options.directives, platformDirectives)
extend(Vue.options.components, platformComponents)

// install platform patch function
Vue.prototype.__patch__ = inBrowser ? patch : noop
Copy the code
Initialize instance members

  • _init()
  • Position the SRC/core/instance/index. Js
  • The constructor is defined and the this._init(options) method is called
  • Common instance members are mixed in for Vue
import { initMixin } from './init' import { stateMixin } from './state' import { renderMixin } from './render' import { eventsMixin } from './events' import { lifecycleMixin } from './lifecycle' import { warn } from '.. 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 _init() This._init (options)} // Register the _init() method of the VM, Initialize vm initMixin(Vue) // register VM $data/$props/$set/$delete/$watch stateMixin(Vue) // initialize event-related methods // $on/$once/$off/$emit $forceUpdate/$destroy lifecycleMixin(Vue) // Add render // $nextTick/_render renderMixin(Vue) export default VueCopy the code
  • initMixin(Vue)
    • What it does: Registers the _init() method of the VM (added on the prototype of the Vue) to initialize the VM
  • stateMixin(Vue)
    • Register data/data/data/props/ set/set/set/delete/$watch for the VM

  • eventsMixin(Vue)
    • Initialize event-related methods, on/on/on/once/ off/off/off/emit

  • lifecycleMixin(Vue)
    • Associated with initialization life cycle method, _update/forceUpdate forceUpdate/forceUpdate/destroy

  • renderMixin(Vue)
    • Add render, $nextTick/_render

SRC /platforms/web/entry-runtime-with-compiler.js
  • Rewrite Vue’s $mount method to add new functionality
$prototype.$prototype = function (el) {$prototype = function (el) {$prototype = function (el); : string | Element, / / the SSR cases to false, SSR is true when hydrating? : Boolean): Component {// Get el object el = el && query(el)... Const options = this.$options // resolve template/el and convert to render function // render template/el if (! Options. render) {let template = options.template // If the template exists... options.render = render options.staticRenderFns = staticRenderFns ... DOM return mount. Call (this, el, hydrating)}Copy the code
  • Determine whether there is a render options, if not render option, will compile template template to render function, and then call the mount method (/ SRC/platforms/web/runtime/index of js $mount), rendering the DOM
  • Vue adds a static member compile method to compile HTML strings into the render function
if (! options.render) { let template = options.template if (template) { ... } } Vue.compile = compileToFunctions export default VueCopy the code
5. Execute _init() to continue initializing the instance member

  • When both the static and instance members are initialized, the Vue constructor is called, where the _init() method is called
  • _init is initialized in initMixin, primarily for Vue instances
export function initMixin (Vue: Class<Component>) {// Add _init() method to Vue instance // merge options // vue.prototype. _init = function (options? : Object) { ... $children/$parent/$root/$refs initLifecycle(vm) /$children/$parent/$root/$refs initLifecycle(VM) // $slots/$scopedSlots/_c/$createElement/$attrs/$listeners InitRender (vm) // beforeCreate Life hook callback callHook(vm, 'beforeCreate') // inject the inject member into the VM initinjection (VM) // resolve the vm before data/props injection _props/methods/_data/computed/watch initState(VM) // Initialize provide initProvide(VM) // resolve provide after data/props // CallHook (VM, 'created')... }}Copy the code
  • initState()
  • Initialize _props/methods/_data/computed/watch of the VM
// /vue/src/core/instance/state.js export 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) } } - initPropsCopy the code

In instance/state.js, we get $options from the Vue instance, and then check whether options has props,methods,data, computed, and watch attributes. If so, we initialize it with initProps

InitProps (VM, opts.props) takes two parameters, one is the Vue instance, and the other is the props attribute. We jump to the initProps function and define an _Props object for the Vue instance and store it in a constant

const props = vm._props = {}
Copy the code

Then, all properties of PropsOptions are iterated over, which is essentially the second parameter in the initProps method. Each property is iterated over and injected into the Props object via defineReactive, which is the vm._props all members are defin EReactive is converted to GET and set, and finally stored on the Props object,

Pay attention to

In development mode, a warning is issued if we assign this attribute directly

Properties in props are converted to GET and set directly in production via defineReactive

Finally, we check whether the props attribute exists in the Vue instance. If not, we inject our properties into the Vue instance through the Proxy function

By calling in the Proxy Object. DefineProperty (target, key, sharePropertyDefinition)

Summary: The function of initProps is to convert our Props members into responsive data and inject it into the Vue instance

  • In initMethods

InitMethods is used to inject methods of options into the vue instance. Before injection, it checks whether the name exists in Props and the naming convention. _ and $are not recommended

  • In initMethods (vm, Opts. Methods (), also receives two parameters, methods in Vue instance and options, first obtains Props in options, then iterates through all properties of methods, then determines whether the current environment is a development environment, and then determines whether methods are functicon

  • If the methods method name exists in the Props object, a warning will be sent if the methods name exists in the Props object. The warning already exists in the Props object because both methods and Props are injected into the Vue instance

  • We continue to determine whether the key exists in Vue and call isReserved(key) to determine whether our key begins with an _ or $

  • Bind (methods[key], vm); / / bind(methods[key], vm)

  • initData(vm)

  • InitData (VM) is called when options has data option

  • Observe (vm._data = {}, true). Observe is one of the functions in the response

  • GetData (data,vm); getData(vm);

  • Get all properties of data and all properties of props and methods

// src/core/instance/state.js
const keys = Object.keys(data)
const props = vm.$options.props
const methods = vm.$options.methods
Copy the code

Finally, do a reactive processing

observe(data, true)
Copy the code

At the end of the _init function, $mount is called again to mount the entire page (first rendering)

// src/core/instance/init.js

if (vm.$options.el) {
  vm.$mount(vm.$options.el)
}
Copy the code
Six, summarized
  • Before rendering for the first time, Vue initialization is performed to initialize both static and instance members
  • When initialization is complete, we call the Vue constructor new Vue(), which calls the _init() method, which acts as an entry point for our entire Vue
  • In the _init method, we finally call mount, there are two mounts, there are two mounts, there are two mounts, the first of which is defined in the entry-runtime-with-Compiler.js file, which is our entry file The core function of mount() is to help us compile the template into the render function, but it will first determine if the render option is currently passed in, and if not, it will retrieve our template option. If template is not available, it will take the el as our template and compile it into render function, which compileToFunctions(). When we compile the render function, It will store the render function in our options.render.
  • Then invokes the SRC/platforms/web/runtime/index. The methods of the mount of js file, in the first to get el, because if is the runtime version, Js is not used to retrieve the EL from entry runtime− With − Compiler. js, so for the runtime version, we will retrieve the EL from the runtime/index.js mount method first, because for the runtime version, Js is not used to retrieve the EL from entry runtime-with-Compiler. js, so if the runtime version is used, we will retrieve the EL in the runtime/index.js mount method first, because if the runtime version is used, The entry runtime−with− Compiler.js entry is not used to get the EL, so for runtime versions we will retrieve the EL in mount() of runtime/index.js.
  • Then called mountComponent (), the method in the SRC/core/instance/lifecycle. Js, defined in the mountComponent (), will first render options, if there is no render options, but we pass in the template, And it will send a warning if we are currently using the runtime version of Vue and we passed in the template instead of render, telling us that the runtime version does not support the compiler. The beforeMount hook function in the lifecycle is then triggered, just before mounting begins.
  • Then we define updateComponent(), which calls vm._render and vm._update. Vm. _render generates the virtual DOM, and vm._update converts the virtual DOM to the real DOM and mounts it to the page
  • Create the Watcher object. When you create Watcher, you pass in the updateComponent function, which is ultimately called from within Watcher. When the Watcher is created, the mounted hook function is triggered. Inside the get method, updateComponent() is called.
  • The mount ends and the Vue instance is finally returned.