乐趣区

关于vue.js:微型Vue框架构建Part4Render渲染前

微型 Vue 框架构建 Part1——根本目录构造
微型 Vue 框架实现 Part2——数据代理实现
微型 Vue 框架构建 Part3——$Mount 办法实现

概述

  • 在上文 $Mount 办法实现中,咱们依据入口点剖析了剖析了 HTML 构造,且为每一个 HTML 节点构建了虚构 DOM(vnode)。本文将在此基础上实现 Render 渲染前的一些筹备工作,为 Render 渲染数据打下基础。
  • 前面渲染数据时,咱们就能依据模板语法和 vnode 的关系,找到对应的数据变量,通过虚构 DOM 渲染到页面中
  • 指标概览

剖析页面中哪些地方用了模板语法

  • HTML 代码

      <div id="app">
          文本内容:<span class="a">{{content}}</span>
          <span class="b">{{info.school}}</span>
      </div>
  • 依据上文,为每一个节点构建的虚构 DOM(vnode),如下图
  • 咱们能看到打印出的 vnode 节点中,text 属性值就是页面中用到模板语法

    入口办法——parpaerRender

      /**
       * mount 办法的具体实现
       * @param {*} vm
       * @param {*} el 挂载节点对应的实在 DOM
       */
      function mount(vm, el) {
        // 第一步:构建虚构 DOM
        const rootDom = getDom(el);
        vm._vnode = contrucVNode(vm, rootDom, null);
    
        // 第二步:收集 DOM 节点和模板语法的映射关系——待实现
        parpaerRender(vm, vm._vnode);
      }

    解析 vnode 和模板愈发的关系

  • 咱们不仅须要晓得页面中哪些地方用到了模板语法,还须要晓得他们之间映射关系。前期咱们批改数据时可能同步页面中的展现内容。
  • 什么样的映射关系?:

    1. 单个的 vnode 节点中,用到了哪些模板语法
    2. 单个的模板语法,有哪些 vnode 节点用到了。
  • 应用 ES6 中 Map 对象

代码实现——parpaerRender 办法

  • nodeType 为 3,示意是以一个文本节点
  • analysisTemplteString:剖析模板
  •   /**
      * 剖析虚构 DOM 中的模板语法和文本
      * @param {*} vm
      * @param {*} vnode
      */
     export function parpaerRender(vm, vnode) {if (vnode.nodeType === 3) {analysisTemplteString(vnode);
       }
    
       for (let i = 0; i < vnode.children.length; i++) {parpaerRender(vm, vnode.children[i]);
       }
     }

    ### 代码实现——analysisTemplteString()

    • 用正则表达式找到单个 vnode 中有哪些模板语法,形如{{xxx}}
    • 有应用到模板语法的,就拿去生成对应的映射关系

      /**
      * 剖析文本类型的虚构 DOM
      * @param {*} vnode
      */
       function analysisTemplteString(vnode) {console.log("-vnode--", vnode);
      const template = vnode.text.match(/{{[\s|a-zA-Z0-9_.|\s]+}}/g);
      if (template && template.length) {for (let i = 0; i < template.length; i++) {
          // 收集依赖
          setTemplateToVNode(template[i], vnode);
          setVNodeToTemplate(template[i], vnode);
        }
      }
       }

    失去映射关系

  • 下图是咱们失去的映射关系,templateToVNode 打印后果,能够看出应用到 contnet 变量 的,只用一个 vnode 节点;VNodeToTemplat 打印的后果,能够看出 单个 vnode 节点 下,应用到的模板语法

  • 代码实现

      const templateToVNode = new Map();
      const VNodeToTemplate = new Map();
      
      /**
       *
       * @param {*} template
       * @returns 模板语法内容,形如{{xxx}}, 返回 xxx
       */
      function getTemplate(template) {if (typeof template !== "string") return;
        if (template.startsWith("{{") && template.endsWith("}}")) {return template.substring(2, template.length - 2);
        }
        return "";
      }
      
      /**
       * 收集依赖:形如 {{xxx}} 的语法模板,那些 vnode 应用到了
       * @param {*} template
       * @param {*} vnode
       */
      function setTemplateToVNode(template, vnode) {const templateName = getTemplate(template);
        const setVNode = templateToVNode.get(templateName);
        if (setVNode) {setVNode.push(vnode);
        } else {templateToVNode.set(templateName, [vnode]);
        }
      }
    
      /**
       *  收集依赖:繁多的 vnode 节点, 用到了哪些形如 {{xxx}} 的语法模板
       * @param {*} template
       * @param {*} vnode
       */
      function setVNodeToTemplate(template, vnode) {const setTemplate = VNodeToTemplate.get(vnode);
        if (setTemplate) {setTemplate.push(template);
        } else {VNodeToTemplate.set(vnode, [template]);
        }
      }
    
退出移动版