This is the 23rd day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
The core process of Vue initial rendering is roughly as follows: parsing the template to generate the render function, calling the render function to generate the virtual DOM, and creating real DOM rendering through the virtual DOM to display in the browser
The core processes
Now that the render function is generated, the mount process starts with the $mount function, adding the mountComponent function as the mount entry point
/** * render process */
Vue.prototype.$mount = function (_el) {
const vm = this;
const ops = this.$options;
const el = document.querySelector(_el);
if(! ops.render) {// There is no render function, need to compile it
let template = ops.template;
if(! template && el) {// No template is passed and el is passed
template = el.outerHTML; // use the content of el as a template
}
// Convert template to render
const { render } = compileToFunction(template);
//
ops.render = render;
}
// Mount the component
mountComponent(vm, el);
};
Copy the code
The initial rendering flow is something that needs to be done within the Vue lifecycle, the mountComponent function is extracted into lifecycle
export function mountComponent(vm, el) {
const options = vm.$options;
vm.$el = el; // Real DOM elements
// todo ...
}
Copy the code
There are two main things you do in this function
- call
render
The function generates the virtual DOM - Create a real DOM rendering from the virtual DOM
_render
Note that _render internally calls the render function above
Vue.prototype._render = function () {
const vm = this;
const { render } = vm.$options;
// render retrievals the value on the instance and returns vnode
return render.call(vm);
};
Copy the code
_update
The virtual DOM is returned by calling _render, the real DOM is created and rendered, and important operations are extracted into the Patch function
Vue.prototype._update = function (vnode) {
const vm = this;
// We need to create real nodes with virtual nodes instead of real $el
vm.$el = patch(vm.$el, vnode);
};
Copy the code
Here you get the mountComponent core work
vm._update(vm._render());
Copy the code
render
The data structure returned when Render is called
function render() {
with(this) {
return _c('div', {
attrs: {
"id": "app"
}
}, [_c('p', [_v("hi " + _s(msg))]), _v(" hello")]}}Copy the code
These _c, _v and other functions return the virtual DOM. Let’s see how these functions are implemented
Encapsulate the implementation of _c, _v, _s and other functions in SRC /render.js and execute them by referencing them in SRC /index.js
Add two lines of code to index.js
+++ import { renderMixin } from "./render"; / / reference
+++ renderMixin(Vue); / / execution
Copy the code
Render. Js general structure
export function renderMixin(Vue) {
/** * _c creates the element's virtual node * _v creates the text's virtual node * _s json.stringify */
Vue.prototype._c = function () {};
Vue.prototype._v = function (text) {};
Vue.prototype._s = function (val) {};
}
Copy the code
Creating a virtual DOM
_c and _v are used to create what are often called virtual nodes. Let’s start with vnode, which creates the virtual DOM
const vnode = (tag, data, key, children, text) = > {
return {
tag,
data,
key,
children,
text,
};
};
Copy the code
_c: the virtual node used to create the element, internally based on createElement
/** * Creates a virtual node for the element */
const createElement = (tag, data, ... children) = > {
let key = data && data.key;
if (key) {
delete data.key;
}
return vnode(tag, data, key, children, undefined);
}
const _c = function () {
returncreateElement(... arguments); };Copy the code
_v: the virtual node used to create text, internally created from createTextNode
/** * Create a virtual node for text */
const createTextNode = (text) = > {
return vnode(undefined.undefined.undefined.undefined, text);
}
const _v = function (text) {
return createTextNode(text);
};
Copy the code
_s: it does something relatively simple, serializing strings
const _s = (val) = > {
return val === null ? "" : typeof val === "object" ? JSON.stringify(val): val;
};
Copy the code
SRC /core/instance/render-helpers/index.js SRC /core/instance/render-helpers/ index.php
export function installRenderHelpers (target) { target._o = markOnce target._n = toNumber target._s = toString target._l = renderList target._t = renderSlot target._q = looseEqual target._i = looseIndexOf target._m = renderStatic target._f = resolveFilter target._k = checkKeyCodes target._b = bindObjectProps target._v = createTextVNode target._e = createEmptyVNode target._u = resolveScopedSlots target._g = bindObjectListeners target._d = bindDynamicKeys target._p = prependModifier }Copy the code
Now that the initial rendering of the Vue is complete and several common functions for creating the virtual DOM have been introduced, we need to look at how to create the real DOM from the virtual DOM and render it to the browser