仿写六、缓存虚拟节点

六、缓存虚拟节点

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

上一篇中,我们使用了闭包来缓存某些数据,将多次的遍历转换为一次遍历。今天这篇,我们使用闭包来缓存 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~

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的桐人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值