为了账号安全,请及时绑定邮箱和手机立即绑定

Vue Dep.target为什么需要targetStack来管理?

Vue Dep.target为什么需要targetStack来管理?

缥缈止盈 2018-11-16 15:15:11
Dep.target = null;var targetStack = [];function **pushTarget** (_target) {  if (Dep.target) { targetStack.push(Dep.target); }  Dep.target = _target;}function **popTarget** () {  Dep.target = targetStack.pop();}Watcher.prototype.get = function get () {  **pushTarget(this)**;  var value;  var vm = this.vm;  if (this.user) {     } else {   }  if (this.deep) {      }  **popTarget();**  this.cleanupDeps();  return value};求教这样做的目的是什么? 不能在选择依赖属性完直接将Dep.target设置为null吗?
查看完整描述

1 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

如果没记错的话 target stack 是 Vue2 中才引入的机制,而 Vue1 中则是仅靠 Dep.target 来进行依赖收集的。根据我自己对 Vue1 和 Vue2 差异的理解,引入 target stack 的原因在于 Vue2 使用了新的视图更新方式。

具体来说,vue1 视图更新采用的是细粒度绑定的方式,而 vue2 采取的是 virtual DOM 的方式。举个例子来说可能比较容易理解,对于下面的模版:

<!-- root -->

<div>

  {{ a }}

  <my :text="b"></my>

  {{ c }}

<div>


<!-- component my -->

<span>{{ b }}</span>

Vue1 的处理方式可以简化理解为:

watch(for a) -> directive(update {{ a }})

watch(for b) -> directive(update {{ b }})

watch(for c) -> directive(update {{ c }})

由于是数据到 DOM 操作操作指令的细粒度绑定,所以不论是指令还是 watcher 都是原子化的。对于上面的模版,在处理完 {{ a }} 的视图绑定后,创建新的 vue 实例 my 并且处理 {{ b }} 的视图绑定,随后继续处理 {{ c }}的绑定。

而在 Vue2 中情况就完全不同,视图被抽象为一个 render 函数,一个 render 函数只会生成一个 watcher,其处理机制可以简化理解为:

renderRoot () {

    ...

    renderMy ()

    ...

}

可以看到在 Vue2 中组件数的结构在视图渲染时就映射为 render 函数的嵌套调用,有嵌套调用就会有调用栈。当 evaluate root 时,调用到 my 的 render 函数,此时就需要中断 root 而进行 my 的 evaluate,当 my 的 evaluate 结束后 root 将会继续进行,这就是 target stack 的意义。

查看完整回答
反对 回复 2018-12-31
  • 1 回答
  • 0 关注
  • 1638 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号