nodeType属性在vue源码中的使用

每个节点都有一个 nodeType 属性,用于表明节点的类型,节点类型由 Node 类型中定义12个常量表示:

 

 nodeType在vue中的应用

在vue编译的过程中需要查找html结构中的双大括号,或者@事件等代表vue中的数据及方法的属性值,通过编译将查找到的部分使用vue实例中的属性或方法替换

class Compile {
    // el是宿主元素选择器
    // vm是KVue实例
    constructor(el, vm) {
        this.$vm = vm;

        this.$el = document.querySelector(el);

        // 先把模板移动到fragment标签中,更新完成后在追加回来
        this.$fragment = this.node2Fragment(this.$el);
        // 执行编译
        this.compile(this.$fragment);
        // 追加
        this.$el.appendChild(this.$fragment);
    }

    node2Fragment(el) {
        // 移动操作
        const fragment = document.createDocumentFragment();
        let child;
        while(child = el.firstChild) {
            // 移动操作
            fragment.appendChild(child);
        }
        return fragment
    }

    // 递归el,分别处理文本节点和元素节点
    compile(el) {
        const childNodes = el.childNodes;
        Array.from(childNodes).forEach(node => {
            if (node.nodeType == 1) {
                // 元素节点 <p k-text="abc" @click="onClick"></p>
                // console.log('元素节点:'+node.nodeName);
                this.compileElement(node);
            } else if (this.isInter(node)) {
                // 文本节点,且内容是{{xxx}}实行
                // console.log('插值文本:'+node.textContent);
                this.compileText(node);
            }

            // 递归子节点
            if (node.childNodes && node.childNodes.length > 0) {
                this.compile(node);
            }
        })

    }
    // 文本节点,且内容是{{xxx}}实行
    isInter(node) {
        return node.nodeType == 3 && /\{\{(.*)\}\}/.test(node.textContent)
    }

    // 编译元素节点
    compileElement(node) {
        // 遍历所有属性
        const nodeAttrs = node.attributes;
        Array.from(nodeAttrs).forEach(attr => {
            // 规定:指令以k-xxx="yyy"命名
            const attrName = attr.name; // 属性名称 k-xxx
            const exp = attr.value;// 属性值 yyy
            if (attrName.indexOf('k-') == 0) {
                const dir = attrName.substring(2);
                // 执行指令解析
                this[dir] && this[dir](node, exp)
            }
        })
    }
    compileText(node) {
        const exp = RegExp.$1;
        this.update(node, exp, 'text');
    }

    // 通用update方法
    update(node, exp, dir) {
        // 获取更新函数
        let updator = this[dir + 'Updator'];
        // 初始化,首次页面赋值
        updator && updator(node, this.$vm[exp]);

        // 创建Watcher
        new Watcher(this.$vm, exp, function(value) {
            updator && updator(node, value);
        })
    }

    textUpdator(node, value) {
        node.textContent = value;
    }

    text(node, exp) {
        this.update(node, exp, 'text')
    }

    html(node, exp) {
        this.update(node, exp, 'html')
    }
    htmlUpdator(node, value) {
        node.innerHTML = value;
    }
}

以上是简单的进行属性查找的示例,通过nodeType为1来判断是元素节点,还是文本节点并进行相应的操作。

 

转载于:https://www.cnblogs.com/wyongz/p/11446477.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值