渲染器的简易实现:vue模板在经过compiler编译后,render函数借助h函数是怎样的将compiler编译后的代码转为vnode并转为真实DOM

简单补充一下vue template模板转为真实DOM的过程:

template -> compiler 编译 -> 渲染函数render(调用h函数) -> Vnode(虚拟节点) -> 真实元素 -> 渲染

接下来将通过代码展示实现过程:
// 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="./render.js"></script>
  <script>
    let counter = 1
    // compiler编译template后的结果
    const vnode = h("div", {class: 'black'}, [
      h("button", {onclick: function() {counter++; console.log(counter)}} , '+1'),
      h("h2", null, counter)
    ])

    mount(vnode, document.querySelector('#app'))
  </script>
</body>
</html>
// render.js
// h函数的作用就是将compiler编译后的模板转为vnode(也就是js对象)
function h(tag, property, children) {
  return {
    tag,
    property,
    children
  }
}
// 将vnode转为真实DOM
function mount(vnode, container) {
  // 1. 将tag转为标签
  const el = vnode.el = document.createElement(vnode.tag)
  // 2. 给标签设置对应的属性
  if (vnode.property) {
    for (const key in vnode.property) {
      const value = vnode.property[key]
      // 点击事件
      if (key.startsWith("on")) {
        el.addEventListener(key.slice(2), value)
        console.log(el.click)
      } else {
        el.setAttribute(key, value)
      }
    }
  }
  // 3. 处理children
  if (vnode.children) {
    if (typeof vnode.children === 'string' || typeof vnode.children === 'number') {
      el.textContent = vnode.children
    } else {
      vnode.children.forEach(item => {
        mount(item, el)
      });
    }
  }
  // 4. 将节点挂载到父节点上
  container.appendChild(el)
}

以上呢就是render函数借助h函数是怎样的将compiler编译后的代码转为vnode并转为真实DOM实现的简易过程。

如有错误,欢迎指正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容