VUE虚拟 dom 转换真实dom

2,192 阅读1分钟

VUE虚拟DOM 转换真实DOM - ADNY(2021.7.15 | 01版)

感谢王红元老师

创建虚拟节点vnode最后挂载到app节点上

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src="./renderer.js"></script>
  <script>
    const vnode = h('div', {class: 'adny'}, [
      h('h1', {class: 'ad', style: "color:#fab"}, 'Adny'),
      h('h2', {class: 'er', style: "color:#abf"}, 'Erkelost')
    ])
    mount(vnode, document.querySelector('#app'))
    console.log(vnode);
  </script>
</body>
</html>

返回一个虚拟DOM对象判断对象中各个属性的边界值(只考虑基础数组类型)最后递归children类型

// mount.js
const h = (tag, props, children) => {
    return {
        tag,
        props,
        children
    }
}

const mount = (vnode, container) => {
    // 创建真是元素 在vnode上保存el
    const el = vnode.el = document.createElement(vnode.tag)

    // 处理props
    if(vnode.props) {
        for (const key in vnode.props) {
            const value = vnode.props[key]
            if(key.startsWith('on')) {
                el.addEventListener(key.slice(2).toLowerCase(), value)
            } else {
                el.setAttribute(key, value)
            }
        }
    }

    // 处理children
    if (vnode.children) {
        if (typeof vnode.children === 'string') {
            el.textContent = vnode.children
        } else {
            vnode.children.forEach(e => {
                mount(e, el)
            });
        }
    }

    // 把el挂在到container中
    container.appendChild(el)
}

效果:

image.png