将Vnode渲染位真实dom

一、什么是虚拟dom

vnode 就是一个普通的javascript对象,用来描述我们的真实dom,举一个🌰哈。有一个<div class='extra'>我是div标签<div>,其对应的vnode为

javascript 复制代码
const vnode = {
    tagName: 'div',
    props: {class:'extra'},
    children:['我是div标签']
}

我们发现上面的vnode有tagName,props,children。下面写一个render函数,将上面的vnode渲染为真实dom

二、render 的实现

2.1 简单版本的实现

javascript 复制代码
const render = (vnode) => {
      let dom = document.createElement(vnode.tagName)
      
      if(vnode.props){
          Object.keys(vnode.props).forEach((key) => {
            let value = vnode.props[key]
            dom.setAttribute(key, value)
          })
      }
      
      if(vnode.children) {
          dom.innerText = vnode.children[0]
      }
      
      return dom
}

2.2 children 是多个且嵌套的实现

html 复制代码
<div class='layout-1'>
    我是第一个层 
    <div class="layout-2">
        我是第二层 
        <div class="layout-3">
            我是第三层
        </div>
    </div>
</div>

上面结构对应的vnode如下

javascript 复制代码
const vnode = {
    tagName:"div",
    props:{class:'layout-1'},
    children:[
        '我是第一个层',
        {
            tagName:'div',
            props: {class: 'layout-2'},
            children:[
                '我是第二层',
                {
                    tagName:"div",
                    props:{class:"layout-3"},
                    children:[
                        '我是第三层'
                    ]
                }
            ]
        }
    ]
}

将上面的vnode渲染为真实dom,只需要递归操作就可以了。代码如下

javascript 复制代码
const render = (vnode) => {
    if (typeof vnode == 'string') {
        return document.createTextNode(vnode)
    }

    let dom = document.createElement(vnode.tagName)
    if (vnode.props) {
      Object.keys(vnode.props).forEach((key) => {
        let value = vnode.props[key]
        dom.setAttribute(key, value)
      })
    }

    vnode.children &&
      vnode.children.forEach((element) => {
        dom.appendChild(render(element))
      })
    return dom
  }

上面这样我们就完成啦。当有children我们递归的去render,然后添加到child中,就可以完成嵌套的渲染了。

2.3 组件化渲染

我们日常开发用的框架Vue、React等框架,都是组件化开发,这些框架会讲我们写的jsx或者模板编译为渲染函数,最后调用这个渲染函数生成vnode。所以如果 vnode 是以function时只需要调用然后再render即可。

javascript 复制代码
let vnode = {
    tagName: 'ul',
    props: { class: 'list' },
    children: [
      {
        tagName: 'li',
        children: ['item1'],
      },
      {
        tagName: 'li',
        children: ['item1'],
      },
      () => ({
        tagName: 'h1',
        children: [
          {
            tagName: 'div',
            children: ['h1-div1'],
          },
          {
            tagName: 'div',
            children: ['h1-div2'],
          },
        ],
      }),
    ],
}

render 实现

javascript 复制代码
const render = (vnode) => {
    if (typeof vnode === 'function') {
      vnode = vnode()
    }
    if (typeof vnode == 'string') {
      return document.createTextNode(vnode)
    }

    let dom = document.createElement(vnode.tagName)
    if (vnode.props) {
      Object.keys(vnode.props).forEach((key) => {
        let value = vnode.props[key]
        dom.setAttribute(key, value)
      })
    }

    vnode.children &&
      vnode.children.forEach((element) => {
        dom.appendChild(render(element))
      })
    return dom
}

上面我们就实现了一个简单的渲染器哈。可以将vnode渲染为真实dom。

相关推荐
付朝鲜9 分钟前
用自写的jQuery库+Ajax实现了省市联动
java·前端·javascript·ajax·jquery
coderYYY17 分钟前
多个el-form-item两列布局排齐且el-select/el-input组件宽度撑满
前端·javascript·vue.js·elementui·前端框架
荔枝吖42 分钟前
项目中会出现的css样式
前端·css·html
Dontla1 小时前
何时需要import css文件?怎么知道需要导入哪些css文件?为什么webpack不提示CSS导入?(导入css导入规则、css导入规范)
前端·css·webpack
小堃学编程1 小时前
前端学习(2)—— CSS详解与使用
前端·css·学习
蓝婷儿1 小时前
第一章:HTML基石·现实的骨架
前端·html
Watermelo6171 小时前
前端如何应对精确数字运算?用BigNumber.js解决JavaScript原生Number类型在处理大数或高精度计算时的局限性
开发语言·前端·javascript·vue.js·前端框架·vue·es6
HebyH_1 小时前
2025前端面试遇到的问题(vue+uniapp+js+css)
前端·javascript·vue.js·面试·uni-app
Clockwiseee1 小时前
CSRF记录
前端·csrf
深圳卢先生1 小时前
XSS 和 CSRF 有什么区别?Java Web 如何防御?
前端·xss·csrf