微型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]);    }  }