手写一个mini-vue之渲染系统实现

前言

vue底层的三大核心系统包括了编译时,运行时,响应式系统,因为编译器的实现是比较复杂的,所以我们直接从运行时开始

主要实现

  • h()

    实现读取vnode

  • mount()

    实现处理vnode,将其挂载到指定节点

  • patch()

目录结构

- mini-vue
src
  render.js
- index.html
复制代码

page

<!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>mini-vue</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="./lib/render.js"></script>

    <script>
      // 1.runtime运行时节点配置vnode
      const vnode = h("div", { class: "page-container" }, [
        h("div", { class: "page-title-view" }, [
          h("h1", { class: "title" }, "页面标题"),
        ]),
      ]);
      // 2.将vnode挂在到指定节点上
      mount(vnode, document.querySelector("#app"));
    </script>
  </body>
</html>

复制代码

render

/**
 * 渲染器
 * @param {string} tag
 * @param {object} props
 * @param {any} children
 * @returns
 */
function h(tag, props, children) {
  return {
    tag,
    props,
    children,
  };
}

/**
 * 挂载器
 * @param function vnode
 * @param string node
 */
function mount(vnode, container) {
  // 1.创建真实的节点,并在vnode上保留el
  const el = (vnode.el = document.createElement(vnode.tag));

  // 2.处理props
  if (vnode.props) {
    for (const key in vnode.props) {
      const attr = vnode.props[key];
      // 考虑到边界问题,判断传入的属性是普通属性还是点击事件
      if (key.startsWith("on")) {
        el.addEventLicener(key.slice(2).toLowerCase(), attr);
      } else {
        el.setAttribute(key, attr);
      }
    }
  }
  // 3.处理children
  if (typeof vnode.children === "string") {
    el.textContent = vnode.children;
  } else {
    vnode.children.forEach((item) => {
      mount(item, el);
    });
  }
  // 4.将el挂在到container上
  container.appendChild(el);
}

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享