In vUE source code learning 9: virtual Dom implementation principle, through vm._render generated vnode.

Today’s lesson is how to convert a VNode into a real Dom and insert it into a page.

_update specifies the patch method

In lifecycleMixin, the Vue prototype has a _update method mounted on it, which takes a single parameter, the generated VNode.

export function lifecycleMixin(Vue) {
    Vue.prototype._update = function (vnode) {
        console.log('vnode', vnode)
        // There is both initialization and update
        // Compare the difference between before and after virtual nodes
        const vm = this
        patch(vm.$el, vnode)
    }
}
Copy the code

Patch method

In _update, you implement both updating the Dom and initializing the Dom.

Patch method is the core method of Dom operation.

Create patch.js in the vDOM folder to handle the logic.

In patch, two parameters are accepted, oldVnode and vnode. OldVnode represents the old Dom and vnode represents the new Dom.

If the oldVnode nodeType is equal to 1, then it is a real element and you need to do the following:

  • Find its parent node based on the current VNode
  • After this node, insert the transformed Dom
  • Remove the original VNode
export function patch(oldVnode, vnode) {
    if (oldVnode.nodeType == 1) {
        console.log('Real element')
        // Replace the real Dom with a Vnode
        const parentEl = oldVnode.parentNode;
        let elm = createElm(vnode)
        parentEl.insertBefore(elm, oldVnode.nextSibling)
        parentEl.removeChild(oldVnode)
    }
}

Copy the code

CreateElm method

If the tag passed to the vNode is a string, it is an Element, otherwise it is a text

Create a new Dom in each case

  • If tag is a string, create Element and loop through its children
  • If the tag is undefined, you only need to create the text node

Finally, return enode.el, at which point the page will be rendered.

function createElm(vnode) {
    let { tag, data, children, text, vm } = vnode
    if (typeof tag === 'string') {
        // The virtual node will have an EL attribute corresponding to the real node
        vnode.el = document.createElement(tag)
        children.forEach(child= > {
            vnode.el.appendChild(createElm(child))
        })
    } else {
        vnode.el = document.createTextNode(text)
    }
    return vnode.el

}
Copy the code

Results the image

Vue code snippets

<div id="app" a="111" style="color: red; background: green;">
    hello{{arr}}word
</div>

let vm = new Vue({
    el: '#app',
    data() {
        return { arr: { name: 'qian' } }
    }
});
Copy the code

Pre-update page

Updated page

After the update, you can see that {{arr}} has been replaced with data in data.

Of course, the style here is lost, will be in the later study, one by one.

Article history

  • How does CodeGen convert ast syntax trees into Render strings?
  • Vue source code learning 9: virtual Dom implementation principle