【Vue】源码分析--vdom与html的相互转换

简析

  • vdom是由js对象节点组成的一个树状结构,通过diff算法对比js对象节点来更新,最后映射到原生的dom中
  • 一个简单的dom结构
<div id="container">
    <h1 style="color: red">vdom与html相互转换</h1>
    <p>hello vdom and html</p>
    <ul>
        <li>item #1</li>
        <li>item #2</li>
    </ul>
</div>
  • 对应到js对象节点就是
class VNode {
    constructor(tagName, props, children) {
        /*当前节点的标签名*/
        this.tagName = tagName
        /*当前节点的一些数据信息,比如props、attrs等数据*/
        this.props = props
        /*当前节点的子节点,是一个数组*/
        this.children = children
    }
}

var vNode1 = new VNode('div', { 'id': 'container' }, [
    new VNode('h1', { style: 'color:red' }, ['vdom与html相互转换']),
    new VNode('p', {}, ['hello vdom and html']),
    new VNode('ul', {}, [new VNode('li', {}, ['item #1']), new VNode('li', {}, ['item #2'])]),
])

代码实现

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Vdom与Html的相互转化</title>
</head>
<body>

    <script src="vNode.js"></script>
</body>
</html>
  • vNode.js
// 设置对象属性的方法
var setAttr = function (node, key, value) {
    switch (key) {
        case 'style':
            node.style.cssText = value
            break
        case 'value':
            var tagName = node.tagName || ''
            tagName = tagName.toLowerCase()
            if (tagName === 'input' || tagName === 'textarea') {
                node.value = value
            } else {
                node.setAttribute(key, value)
            }
            break
        default:
            node.setAttribute(key, value)
            break
    }
}

// 虚拟的js对象节点
class VNode {
    // html to vnode
    constructor(tagName, props, children) {
        /*当前节点的标签名*/
        this.tagName = tagName
        /*当前节点的一些数据信息,比如props、attrs等数据*/
        this.props = props
        /*当前节点的子节点,是一个数组*/
        this.children = children
    }

    // vnode to html
    render() {
        // 创建标签
        var el = document.createElement(this.tagName)

        // 设置标签props属性
        var props = this.props
        for (var propName in props) {
            setAttr(el, propName, props[propName])
        }

        // 递归创建子节点children
        this.children.forEach(child => {
            var childNode = (child instanceof VNode) ? child.render() : document.createTextNode(child)
            el.appendChild(childNode)
        })

        return el
    }
}


// html to vNode
var vNode1 = new VNode('div', { 'id': 'container' }, [
    new VNode('h1', { style: 'color:red' }, ['vdom与html相互转换']),
    new VNode('p', {}, ['hello vdom and html']),
    new VNode('ul', {}, [new VNode('li', {}, ['item #1']), new VNode('li', {}, ['item #2'])]),
])

// vNode to html
var rootNode = vNode1.render()
document.body.appendChild(rootNode)

Github

转载于:https://blog.csdn.net/ns2250225/article/details/79548025 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值