概述

  • 本节内容是在上一篇的根底上,实现对象类型的数据渲染,渲染到实在页面中
  • 难点有:

    1. 如何晓得单个vnode中有那些模板语法
    2. 如何实现晓得模板语法对应的值
    3. 如何实现数据的替换,实现页面渲染
  • 流程概览图示

找到模板语法

  • 在上文中咱们实现了模板和vnode之间的互相映射,且用Map对象保留,所以可通过Map的内置办法实现
  • 代码实现

      /**   * 渲染虚构DOM   * @param {*} vm   * @param {*} vnode   */  function renderVNode(vm, vnode) {    if (vnode.nodeType === NODE_TYPE_TEXT) {      const templateArr = VNodeToTemplate.get(vnode);      if (templateArr && templateArr.length) {        for (let i = 0; i < templateArr.length; i++) {            // 1.遍历vnode下所有的模板语法            // 2. 晓得每个模板语法对应的值            // 3. 操作实在DOM,替换模板语法,实现数据渲染            }      }    } else {      for (let i = 0; i < vnode.children.length; i++) {        renderVNode(vm, vnode.children[i]);      }    }  }

    找到模板语法在data中的值

  • vue中的data属性值是一个变量,所以咱们将定义一个办法来实现这个性能
  • 模板的数据可能有两个,一个是data中定义的,一个可能是类型v-for循环这样的局部变量
  • 代码实现

      /**   * 返回模板语法对应的数据   * @param {*} dataArr 数据源   * @param {*} template 模板语法   */  export function getTemplateValue(dataArr, template) {    let templateValue;    if (dataArr instanceof Array) {      for (let i = 0; i < dataArr.length; i++) {        templateValue = getObectValue(dataArr[i], template);        if (templateValue) break;      }    }    return templateValue;  }  function getObectValue(obj, template) {    let tempalteValue;    const keyArr = template.split(".");    for (let i = 0; i < keyArr.length; i++) {      const key = keyArr[i].trim();      const value = obj[key];     if (value instanceof Object) {        // 数据是对象的状况        return (tempalteValue = getObectValue(value, template));      } else {        tempalteValue = obj[key];      }    }    if (!tempalteValue) {      throw new Error(`${template} is not undefined`);    }    return tempalteValue || "undefined";  }

    拿到模板语法的值后,渲染数据

  • 之前咱们定义的vnode中有实在DOM,所以能够间接操作
  • 通过正则实现模板语法的替换
  • 代码实现

     function renderVNode(vm, vnode) {    if (vnode.nodeType === NODE_TYPE_TEXT) {      const templateArr = VNodeToTemplate.get(vnode);      if (templateArr && templateArr.length) {        for (let i = 0; i < templateArr.length; i++) {            // 获取模板语法的值          const templateValue = getTemplateValue(            [vm._data, vnode.env],            templateArr[i]          );          let nodeValue;          console.log("templateValue", templateValue);                      // 如果模板语法有对应的值,就替换模板语法          if (templateValue) {            nodeValue = vnode.text.replace(              new RegExp(`{{[\s|${templateArr[i]}|\s]+}}`, "g"),              templateValue            );          }          // 操作实在DOM,实现数据渲染          vnode.elm.nodeValue = nodeValue;        }      }    } else {      for (let i = 0; i < vnode.children.length; i++) {        renderVNode(vm, vnode.children[i]);      }    }  }