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.