The overall process of template compilation: compile the template into the render function using Vue Template Complier, and then execute the render function to generate a VNode
Pre-knowledge: JSwith
grammar
with
Syntax changes{}
Search rules for free variables in a block, asobj
Property to find- If you don’t find a match
obj
Property, an error is reported with
Use it with caution, it breaks scope rules and makes it less legible
vue template complier
Compile the template torender
function
What are vue templates compiled into?
- Template is not HTML, there are instructions, interpolation, JS expression, can realize the judgment, loop
- HTML is a tag language, only JS can implement judgment, loop (Turing-complete)
- Therefore, the template must be converted to some kind of JS code, how to convert a template to JS code process is template compilation
First we install vue Template Complier, and then we write a template string to see the compiled output
The interpolation to compile
const compiler = require('vue-template-compiler')
/ / the interpolation
// const template = ` {{message}}
`
/ / compile
const res = compiler.compile(template)
console.log(res.render)
Copy the code
The print result is as follows
with(this){return _c('p',[_v(_s(message))])}
Copy the code
This is the VM instance in Vue, so _c _V _S is some functions in vue source code, so let’s search the meaning of these functions in the source code
// Find the meaning of the abbreviation function in vue source code
function installRenderHelpers (target) {
target._c = createElement/ / create a vnode
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
So the transformation is as follows
with(this){return createElement('p',[createTextVNode(toString(message))])}
Copy the code
The createElement function creates a VNode
Expression compilation
The expression is converted to JS code and the result is put into a VNode
const template = ` <p>{{flag ? message : 'no message found'}}</p> `
Copy the code
with(this){return _c('p',[_v(_s(flag ? message : 'no message found')))}Copy the code
Dynamic properties
In the same way
// Dynamic attributes
const template = `
`
Copy the code
with(this){return _c('div',
{staticClass:"container".attrs: {"id":"div1"}},
[
_c('img', {attrs: {"src":imgUrl}})])}
Copy the code
conditions
Use ternary expressions to create different VNodes
/ / conditions
const template = `
A
B
`
with(this){return _c('div',[(flag === 'a')? _c('p',[_v("A")]):_c('p',[_v("B")]])}Copy the code
cycle
The _L (renderList) function returns the list vNode by passing in an array or object
/ / loop
const template = `
- {{item.title}}
`
with(this){return _c('ul',_l((list),function(item){return _c('li', {key:item.id},[_v(_s(item.title))])}),0)}
Copy the code
The event
The ON property contains all the event bindings
/ / event
const template = ` `
with(this){return _c('button', {on: {"click":clickHandler}},[_v("submit")])}
Copy the code
v-model
//v-model
const template = ` <input type="text" v-model="name"> `
// Look at the input event
with(this){return _c('input', {directives: [{name:"model".rawName:"v-model".value:(name),expression:"name"}].attrs: {"type":"text"},domProps: {"value":(name)},on: {"input":function($event){if($event.target.composing)return; name=$event.target.value}}})}Copy the code
- There’s one in the compiled code
on
And to monitor theinput
The event,name=$event.target.value
Delegate assigns the value of the event toname
thename
Is in the component instancename
, i.e.,this.name
。 domProps:{"value":(name)}
On behalf ofvalue
Shows thename
Variables, alsothis.name
In other words, the principle of the V-model is the attr of value plus the syntax sugar of the input event, and then execute the render function to generate the VNode
conclusion
Template compilation process: the template is compiled into the render function, executes the render function to return vNode
Patch and DIff will be implemented later based on vNode (see my article Vue series: Virtual DOM and Diff algorithm in detail).
Note: With Webpack vue-loader, templates are compiled in a development environment (important). So the resulting packaged code is no longer template code, but all render functions. But the vue. Js file that we reference directly with
render
function
You can use Render instead of template in vue components
In complex cases where template is not available, use render instead
To summarize how components are rendered and updated
The component rendering/update process wraps three things:
- Initial rendering process
- The update process
- Asynchronous rendering
The initial rendering process
-
Parsing the template into the render function (webpack uses vue-Loader in the development environment) (this process is how the template compilation works above)
-
Firing responsivity, listening for data properties, setting getter setters (see my article Vue series: Vue2 Responsivity Principles)
-
Execute the render function to generate the VNode, and then execute patch(elem, vnode) to render the VNode to the DOM. Take a closer look at my Vue series: Virtual DOM and Diff Algorithms
The update process
- Modify the
data
To triggersetter
(aftergetter
Is being monitored) - To perform
render
Function, generatenewVnode
patch(vnode, newVnode)
(Diff algorithm)
Summary render update flowchart
The template compiles and then executes the render function, which fires the reactive getter for dependency collection (watcher the getter for any variable fired in the template).
When we modify the data, we fire the setter and notify the Watcher to refire the re-reder for rerendering
Vue components are rendered asynchronously
Review thethis.$nextTick
:
- Vue components are rendered asynchronously. DOM will not render immediately until the code is executed.
this.$nextTick
Is called back when DOM rendering is complete - The page will be rendered
data
Make an integration of the modifications, multiple timesdata
Only one final value will be rendered
This reduces DOM operations and improves performance