仿写六、缓存虚拟节点

六、缓存虚拟节点

自己动手实践,就会更加深刻的理解**”**

上一篇中,我们使用了闭包来缓存某些数据,将多次的遍历转换为一次遍历。今天这篇,我们使用闭包来缓存 vnode,当数据发生改变时,无需重新生成 vnode,而是直接对 vnode 中的 {{data}} 进行替换。

01、combine


我们需要一个函数,来将带有模板 {{data}} 的 vnode与data结合,生成不带有模板的 vnode,此函数为 combine

/**
 * 带{{}}的vnode + data -> vnode
 * @param {MyVNode} vnode 虚拟节点
 * @param {*} data 数据
 */
function combine(vnode, data) {
  const {tag, text, type, data: attrs, children} = vnode;
  let _vnode;
  switch(type) {
    case 1: // 元素节点
      _vnode = new MyVNode(tag, attrs, text, type);
      for (const child of children) {
        _vnode.appendChild(combine(child, data));
      }
      break;
    case 3: // 文本节点
      const newText = text.replace(regMustache, function (_, g) {
        return getValueByPath(data, g.trim());
      })
      _vnode = new MyVNode(tag, attrs, newText, type)
      break;
  }
  return _vnode;
}

02、闭包缓存render函数


值得注意的是,Vue中使用的是 AST + data => vnode,而这里简化,跳过AST,用vnode来代替。

/**
 * 通过AST生成render函数。
 * 目的是缓存AST。
 * 这里用 vnode 来模拟AST。
 */
MyVue.prototype.createRenderFn = function() {
  const vnode = getVNode(this._template);
  /**
   * Vue: AST + data => VNode
   * MyVue: 带{{}}的VNode + data => VNode
   */
  return function render() {
    return combine(vnode, this._data);
  }
}

03、其他函数


MyVue.prototype.$mount = function() {
  this._render = this.createRenderFn(); // 带缓存的render函数
  this.mountComponent();
}

MyVue.prototype.mountComponent = function () {
  this._update(this._render())
}

/** 
 * Vue: diff算法更新vnode
 * MyVue(简化): 将vnode生成DOM放入文档中
 */
MyVue.prototype._update = function (newDOM) {
  this._parent.replaceChild(parseVNode(newDOM), this._template);
}

04、效果图


html部分代码:

<header id="root">
  <p>{{name}}p>
  <p>{{message}}p>
  <p>{{name}} -- {{message}}p>
  <p>{{deep.firstLevel.secondLevel}}p>
header>
<script>
    let app = new MyVue({
        el: '#root',
        data: {
          name: 'romeo',
          message: 'wants to be rich',
          deep: {
            firstLevel: {
              secondLevel: 'awesome'
            }
          }
        }
      })
script>

源代码在github~

仿写六、缓存虚拟节点_第1张图片

你可能感兴趣的:(vue,javascript,html,vue.js)