Main Outline:
- Viewing the Global Configuration of Vue.config from the initGlobal API Method
- Searching for the Origin of the Constructive Function of Ancestor-Vue
Let's start with the most common vue code demo
<div id="app"> {{ message }} </div> // js var vm = new Vue({ el: '#app', data: { message: 'hello vue' } })
A Vue application has been created above; it is easy to see from the above that Vue is a constructor, and vm is an instantiated object constructed with this constructor. When instantiating, parameters are passed in, including el and data.
The above extends three questions:
- What does the Vue constructor look like?
- How can Vm implement the open API of vue in the source code?
- What happened to the parameters we passed into the constructor
These problems are the first steps to unlock the vue source code, so we might as well start looking for the implementation of these source codes through the vue source code entry.
Under the source src/platforms/web, there are different versions of build entry files, which export Vue from src/core/instance/index.
Let's first look at the answers that the entry document can give us:
// src/core/instance/index import Vue from './instance/index' import { initGlobalAPI } from './global-api/index' import { isServerRendering } from 'core/util/env' import { FunctionalRenderContext } from 'core/vdom/create-functional-component' initGlobalAPI(Vue)
This entry file does three things:
- The reference to. / instance/index exposes the source of vue, the constructor
- Invoke initGlobal API method, pass vue in, expand global static method for vue
- Exposing vue
The significance of this entry file is that before exposing vue, it extends the global static method to Vue through initGlobal API method. The external API corresponding to Vue is Vue.config, which includes the global configuration of Vue.
Vue.config.silent // Logs and Warnings Vue.config.errorHandler // When this handler is called, error information and Vue instances can be obtained. Vue.config.devtools // Configuration allows vue-devtools to check code …..
Viewing the Global Configuration of Vue.config from the initGlobal API Method
The initGlobal API method defines the configDef object, and its getter method has a property value of config. The setter method gives a warning that modifications are not allowed. Finally, the config attribute is added to vue, and the attribute description returns the configDef object.
export function initGlobalAPI (Vue: GlobalAPI) { // config const configDef = {} configDef.get = () => config if (process.env.NODE_ENV !== 'production') { configDef.set = () => { warn( 'Do not replace the Vue.config object, set individual fields instead.' ) } } Object.defineProperty(Vue, 'config', configDef) // Add config attributes
In addition, util attributes are defined, but they are not exposed to the outside world and are not recommended for external use.
Searching for the Origin of the Constructive Function of Ancestor-Vue
Knowing the constructor, you know what happens when new vue()
The following code is the construction method of Vue. We can intuitively see that the Vue constructor uses ES5 Function to implement classes, because we can extend many methods to Vue prototype by prototype, and split these methods into different files/modules, which is more conducive to code maintenance and collaborative development.
For example, in this file, you can see that Vue is passed as a parameter into the following ** Mixin methods, which define some functions on its prototype by receiving vue.
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') // vue must be an instantiated object of new vue() } console.log('options', options) this._init(options) // Call the internal_init method } initMixin(Vue) // Operations before the created lifecycle function stateMixin(Vue) // Subscription and Publication of Static Data Using Defined Property eventsMixin(Vue) // Instance event flow injection utilizes event flow construction of subscription publishing mode lifecycleMixin(Vue) // renderMixin(Vue) // Implementing _render rendering virtual dom export default Vue
The core of this constructor is this._init(options)
At this breakpoint, you can see that the parameter options come in just the parameters el and data that we passed in when we instantiated them outside.
new Vue({ el: '#app', data: { message: 'hello vue' } })
This _init method comes from the initMixin function
After looking at this function, we sorted out several important nodes of the source code in the whole initialization phase.
- Initialize options parameters for merge configuration
- Initialization life cycle
- Initialization time system
- Initialize state, including data, props, computed, watcher
export function initMixin (Vue: Class<Component>) {
console.log('Vue', Vue) Vue.prototype._init = function (options?: Object) { const vm: Component = this // The uid of a uid instantiation is incremented by 1 vm._uid = uid++ let startTag, endTag /* istanbul ignore if */
...
// Identifying the current instance as a Vue instance with _isVue is done for subsequent observation vm._isVue = true // Configure options and determine if it is the initialization of options for internal Component s? if (options && options._isComponent) { // inside initInternalComponent(vm, options) } else { // Non internal vm.$options = mergeOptions( resolveConstructorOptions(vm.constructor), options || {}, vm ) } // Point this to vm._renderProxy in render if (process.env.NODE_ENV !== 'production') { initProxy(vm) } else { vm._renderProxy = vm } // expose real self vm._self = vm // Initialization life cycle initLifecycle(vm) // Initialize event registration initEvents(vm) // Initialization rendering initRender(vm) // The beforeCreate hook function in the trigger drop function callHook(vm, 'beforeCreate') initInjections(vm) // resolve injections before data/props // Initialize the state of vm, including data, props, computed, watcher, etc. initState(vm) initProvide(vm) // resolve provide after data/props // vm has been created and the created hook function is dropped callHook(vm, 'created') /* istanbul ignore if */ … // Mount instances if (vm.$options.el) { vm.$mount(vm.$options.el) } }
}