MVVM原理(建立虚拟DOM树)

1.创建虚拟节点的类,这里使用es6语法糖。

export default class VNode {
    constructor(
        // 节点类型和标签类型的区别是什么?
        tag, // 标签类型,DIV,SPAN,INPUT,#text
        ele, // 对应的真实节点
        children, // 当前节点下的子节点
        text, // 当前虚拟节点的文本
        data, // VNodeData,暂时保留,暂无意义
        parent, // 父级节点
        nodeType, // 节点类型
    ) {
        this.tag = tag;
        this.ele = ele;
        this.children = children;
        this.text = text;
        this.data = data;
        this.parent = parent;
        this.nodeType = nodeType;
        this.env = {}; // 当前节点的环境变量,这个是自己设定的
        this.instructions = null; // 存放指令的
        this.template = []; // 当前节点涉及到的模板
    }
}

2.构建虚拟DOM树并且挂载到Vue上,使用深度先搜索构建虚拟DOM树。

import VNode from "../vnode/vnode.js";

export function initMount(Vue) {
    Vue.prototype.$mount = function (el) {
        let vm = this;
        let rootDom = document.getElementById(el);
        mount(vm, rootDom);
    }
}

export function mount(vm, ele) {
    // 进行挂载
    vm._vnode = constructVNode(vm, ele, null);
    // 进行预备渲染(简历渲染索引,通过模板找vnode,通过vnode找模板)
}

function constructVNode(vm, ele, parent) {
    let vnode = null;
    let children = [];
    let text = getNodeText(ele); // 不确定是否有文本,只有文本节点才有文本
    let data = null;
    let nodeType = ele.nodeType;
    let tag = ele.nodeName;
    vnode = new VNode(tag, ele, text, data, parent, nodeType);

    // 获取子节点
    let childs = vnode.ele.childNodes;
    // 深度优先算法DFS
    for (let i = 0; i < childs.length; i++) {
        let childNode = constructVNode(vm, childs[i], vnode);
        if (childNode instanceof VNode) { // 返回单一节点的时候
            vnode.children.push(childNode);
        } else { // 返回节点数组
            vnode.children = vnode.children.concat(childNode);
        }
    }
    return vnode;
}

function getNodeText(ele) {
    if (ele.nodeType === 3) { // 标签类型为#TEXT时
        return ele.nodeValue;
    } else {
        return '';
    }
}
原创文章 28 获赞 52 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq1123642601/article/details/104451492