vue模板编译

本文深入探讨Vue.js的模板编译过程,从模板到渲染函数的转换,涉及虚拟DOM、指令处理、条件与循环、组件编译等方面,揭示Vue如何高效地实现视图更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  /* 正则 */
    let regular = /\{\{(.+?)}\}/g;
    function compile(template, data) {
        //查找模板下的所有子元素
        let childNodes = template.childNodes;
        for (let i = 0; i < childNodes.length; i++) {
            //查找子元素节点类型 1=== 元素  3===文本
            let type = childNodes[i].nodeType
            //判断 3 文本
            if (type === 3) {
                //文本子节点的值
                let textContent = childNodes[i].nodeValue // {{xxxxxxx}}
                //进行替换
                let text = textContent.replace(regular, (_, g) => {
                    let path = g.trim() // name age love 
                    let value = valueBypath(data, path) //赋值
                    return value
                })
                //dom和值关联
                childNodes[i].nodeValue = text
            } else if (type === 1) {
                //如果type 是 1
                compile(childNodes[i], data)
            }
        }
    }
    //xxx.xxx.xxx 格式  
    function valueBypath(obj, path) {
        let paths = path.split(".")
        let res = obj
        let props
        while (props = paths.shift()) {
            res = res[props]
        }
        return res
    }
    class ssjVue {
        constructor(options) {
            /* 挂在元素 */
            this._data = options.data  
            this._el = options.el
            this.$el = this._templateDom = document.querySelector(this._el)
            /* 因为ithis.$el会被替换 设置其上级元素 */
            this._parent = this._templateDom.parentNode;
            /* 渲染 html */
            this.render()
        }
        /* 渲染 */
        render() {
            this.compiler();
        }
        /* 编译 */
        compiler() {
            let realHtomlDom = this._templateDom.cloneNode(true)
            compile(realHtomlDom, this._data);
            this.update(realHtomlDom)
        }
        /* 更新 */
        update(real) {
        	this._parent.replaceChild(real,docunment,querySelector(`${this._el}`))   
        }
    }
    /* 虚拟dom */
    class Vnode {
        /* 
            tag:标签名字 div
            data:数据  class id title 等
            value:文本节点
            type  1 div 3 文本 p 。。。。
         */
        constructor(tag, data, value, type) {
            this.tag = tag && tag.toLowerCase();
            this.data = data
            this.value = value
            this.type = type
            this.children = []
        }
        appendChild(vnode) {
            this.children.push(vnode)
        }
    }
    /* 
        使用递归 来遍历 DOM 元素 生成 dom
     */
    function getVnode(node) {
        let nodeType = node.nodeType
        let _vnode = null
        switch (nodeType) {
            case 1:
                //元素
                let nodeName = node.nodeName
                let attrs = node.attributes
                let _attrObj = {}
                for (let i = 0; i < attrs.length; i++) { //attrs[i] 属性节点(nodeType == 2 )
                    _attrObj[attrs[i].nodeName] = attrs[i].nodeValue
                }
                _vnode = new Vnode(nodeName, _attrObj, undefined, nodeType)
                //考虑node的子元素 
                let childrenNodes = node.childNodes;
                for (let i = 0; i < childrenNodes.length; i++) {
                    _vnode.appendChild(getVnode(childrenNodes[i])) //递归
                }
                break;
            case 3:
                //文本
                _vnode = new Vnode(undefined, undefined, node.nodeValue, nodeType)
                break
        }
        return _vnode
    }
    /* 解析vnode  生成真实dom*/ /* 下一步 添加 属性 */
    function parseVnode(vnode) {
        /* let vnode = vnode */
        let realnode = vnode
        console.log(realnode)
        let realnodeType = realnode.type
        console.log(realnodeType)
        let _realnode = null
        if (realnodeType === 1) {
            let nodeName = realnode.tag
            let attrs = realnode.data
            let attrsObj = {}
            for (let i = 0; i < attrs.length; i++) { 
               // _attrObj[attrs[i].nodeName] = attrs[i].nodeValue
            }
            _realnode = document.createElement(nodeName)
            let childrenNodes = realnode.children;
            console.log(childrenNodes)
            for (let i = 0; i < childrenNodes.length; i++) {
                _realnode.appendChild(parseVnode(childrenNodes[i])) //递归
            }

        } else if (realnodeType === 3) {
            _realnode = document.createTextNode(vnode)
        }
        return _realnode
    }
    let app = new ssjVue({
        el: '#root',
        data: {
            name: 'ssj',
            age: 22,
            love: 'playgame',
            over: {
                xixi: 1111
            }
        }
    })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值