How does CodeGen convert ast syntax trees into Render strings?
In the vue source code learning (8) article, we explained in detail how the AST syntax tree is converted into the Render string.
Today’s tutorial is how to generate a VNode using the Render string.
Template engine
The template engine in Vue is implemented with new Function + with.
When we pass the string to new Function(), we get the following Function.
function anonymous() {
_c('div', {id:"app".a:"111".style: {"color":" red"."background":" green"}}),_v("hello"+_s(arr)+"word")}Copy the code
At this point, you can see that _s(arr) comes from the VM, but the new Function does not get the VM. So that’s where “with” comes in.
So the following is done:
// change code to 'with(this){return ${code}}'
let render = new Function(code)
// Replace it with the following
let render = new Function(`with(this){ return ${code}} `)
Copy the code
With the above delivery, it can be used like this:
render.call(vm)
Copy the code
Tip 💡 : New Function can be thought of as a sandbox, creating scopes parallel to the global scope
With the use of the
The with statement was originally intended to provide a namespaces style shorthand for hierarchical object access.
Here’s an example:
// Suppose you have an obj object and want to modify each item in obj
var obj = {
a: 1.b: 2.c: 3
};
// Method 1: Modify obj one by one and use obj three times
obj.a = 2;
obj.b = 2;
obj.c = 2;
// Method 2: use obj once
with (obj) {
a = 3;
b = 3;
c = 3;
}
Copy the code
mountComponent
MountComponent, as the name suggests, generates components.
The implementation code is as follows:
export function mountComponent(vm, el) {
console.log(vm, el)
// After the data changes, the update function is called again
let updateComponent = () = > {
// 1. Generate the virtual DOM with render
vm._update(vm._render()) // Subsequent updates can invoke the updateComponent method
// 2. Virtual Dom generates real Dom
}
updateComponent()
}
Copy the code
- UpdateComponent: Updates the function when data changes
- Vm. _update: Mount the _update method on the prototype of Vue to update it
- Vm. _render: Mount the _c, _V, _S, _render methods on the prototype of Vue
export function renderMixin(Vue) {
Vue.prototype._c = function (tag, data, ... children) {
console.log(tag, data, children)
// Create a virtual node
return createElement(this. arguments) } Vue.prototype._v =function (text) {
console.log(text)
// Create a virtual node
return createTextElement(this, text)
}
Vue.prototype._s = function (val) {
console.log(val)
// Create a virtual node
return JSON.stringify(val)
}
Vue.prototype._render = function () {
console.log('render')
const vm = this
let render = vm.$options.render
let vnode = render.call(vm)
returnvnode; }}Copy the code
VDom
CreateElement and createTextElement are used in vm._render to generate a virtual Dom.
The implementation code is as follows:
export function createElement(vm, tag, data = {}, ... children) {
console.log('abc', vm, tag, data, children)
return vnode(vm, tag, data, data.key, children, undefined)}export function createTextElement(vm, text) {
console.log('def', vm, text)
return vnode(vm, undefined.undefined.undefined.undefined, text)
}
function vnode(vm, tag, data, key, children, text) {
return {
vm,
tag,
data,
key,
children,
text
}
}
Copy the code
The above content is only for learning to use.