This article is taken from my public account [Sun Wukong, Don’t talk nonsense]
Continue with the previous preparation. We know that in Vue2.6.10, the entry file is in SRC /platforms/web/entry-runtime-with-compiler.js. So let’s take a look at the code inside.
When looking at the source code for the first time, there are two things worth noting:
- Don’t focus on details, grasp the overall direction, to be swallowed in a way.
- Set reading goals and focus on reading.
Let’s start by looking at our target: where exactly is the Vue constructor? What is the initialization process?
Trace the Vue constructor
Let’s start with the core of the entry-runtime-with-Compiler.js file:
// extend the $mount function, Const mount = Vue. Prototype.$mount. Prototype.$mount = function (el? : string | Element, hydrating? : boolean ): Component {el = el && query(el) // Handles user defined options, $options // resolve template/el and convert to render function if (! Options. render) {let template = options.template if (template) {// String template if (typeof template === 'string') {// selector if (template.charAt(0) === '#') { template = idToTemplate(template) /* istanbul ignore if */ if (process.env.NODE_ENV ! == 'production' && ! template) { warn( `Template element not found or is empty: ${options.template}`, This)}}} else if (template.nodetype) {// Dom template = template.innerhtml} else {if (process.env.node_env! == 'production') {warn('invalid template option:' + template, this)} return this}} else if (el) { // It is worth noting that, Template = getOuterHTML(el)} if (template) {// get render const {render, staticRenderFns } = compileToFunctions(template, { outputSourceRange: process.env.NODE_ENV ! == 'production', shouldDecodeNewlines, shouldDecodeNewlinesForHref, delimiters: options.delimiters, comments: options.comments }, This) options.render = render options.staticRenderFns = staticRenderFns}} return mount. Call (this, el, hydrating) }Copy the code
As you can see from the code, this file simply enhances the existing mount function by processing the custom template options entered by the user and rendering the render function.
Conclusions can be drawn from this:
1. If el, render, and template variables are present at the same time, the priority order is render > template > el.
2. CompileToFunctions (which convert templates to render functions) are very early in the initialization process, before the specific mount function is executed.
This is not where the real Vue constructor is. /runtime/index.js:
Vue. Prototype.__patch__ = inBrowser? Prototype.$prototype.$prototype = function (prototype); : string | Element, hydrating? : boolean ): Component { el = el && inBrowser ? Query (el) : undefined // This is the true mount function return mountComponent(this, el, hydrating)}Copy the code
It turns out that the file simply defines the __patch__ function and the $mount function on the prototype chain. The detailed mount process is not here. We won’t look at the details.
Keep looking for: core/index.js
// Initialize the global API initGlobalAPI(Vue)Copy the code
The results were still disappointing. Can not help feeling: this Russian nesting doll is too many layers. Inside core/index.js, it just initializes the global API. This is not our focus today, still continue to find: the SRC/core/instance/index, js:
function Vue (options) {
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
Copy the code
Here, the Vue constructor is finally found!! At the same time, we also found that this file performs many Mixin operations. Let’s ignore the details and look at what this._init() does in the constructor.
Can be through browser debugging, the prototype by global searching. _init way, find _init () in the file: SRC/core/instance/init. Js.
// Order of initialization: Lifecycle -> Event Listener -> Render ->beforeCreate-> Injection -> State initialization ->provide->created VM._self = VM initLifecycle(VM) initEvents(VM) initRender(vm) callHook(vm, 'beforeCreate') initInjections(VM) // resolve before data/props initState(VM) // initialize the function Props/data/watch/the methods, the will is the key of the research data response initProvide (vm) / / resolve dojo.provide after data/props callHook (vm, 'created') // If there is an EL element, $mount is automatically implemented, which is also important to understand. $mount if (vm.$options.el) {vm.$mount(vm.$options.el)}Copy the code
Conclusions can be drawn from this:
1. In _init(), we see the execution order of vue instance initialization: life cycle -> Event listener -> Render ->beforeCreate-> Inject data -> Component state initialization -> Provide data -> Created.
2. If there is an EL element, the mount is automatically performed.
If we want to understand the details of data responsiveness, we should look at the initState() function in detail. That’s going to be the focus of our next lecture.
At this point, we find the main document context. As for the specific initialization process, we need to take a closer look at what is done in the $mount process. So let’s go back to the actual mount function mountComponent() and see what happens:
Export function mountComponent (vm: Component, el:? Element, hydrating? : boolean ): Component { ... CallHook (vm, 'beforeMount') let updateComponent /* Istanbul ignore if */ if (process.env.node_env! == 'production' && config.performance && mark) { ... } else {updateComponent = () => {// updateComponent does two things: Vm._update (vm._render(), hydrating)}} New Watcher(vm, updateComponent, noop, {before () {if (vm._isMounted &&! vm._isDestroyed) { callHook(vm, 'beforeUpdate') } } }, true /* isRenderWatcher */) hydrating = false if (vm.$vnode == null) { vm._isMounted = true callHook(vm, 'mounted') } return vm }Copy the code
In the code above, we see that a new Watcher is created during the vue instance mount. This Watcher acts like an observer, executing the updateComponent function if it receives a message that the data has changed. The updateComponent function does two main things: render(generate vDOM) and update(convert VDOM to DOM).
To sum up, the flow chart is as follows:
So, how does Watcher work, and how does it play into the overall process of data responsiveness? The next article will give you the answer!
Vue source code interpretation
(1) : Vue constructor and initialization process
(II) : Data response and implementation
(3) : array responsive processing
(iv) Vue’s asynchronous update queue
(5) The introduction of virtual DOM
(VI) Data update algorithm — Patch algorithm
(7) : realization of componentization mechanism
(8) : computing properties and listening properties
The Optimize stage of the compilation process
Vue
Vue’s error handling mechanism
Parse the working process of Vue in handwritten code
Vue Router handwriting implementation