李恒道 发表于 2022-1-2 01:23:07

vue计算函数新旧变化

# 前文

只是自己的一次无聊想法

很基础的内容

大佬不要嘲笑

# computed变化

vue对computed进行了响应优化

这里拿了2.5.6和2.5.17做对比

![图片.png](data/attachment/forum/202201/02/011849wk64ceu613gnl4qk.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "图片.png")

2.5.17提示的是RangeError: Maximum call stack size exceeded

具体改变在于哪呢?

在源码的Watcher.prototype.update位置

![图片.png](data/attachment/forum/202201/02/011916yry1wvm282vxsws8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "图片.png")

看注释和代码来说,大概意思是早期是判断deps是否为0,如果为0则再下轮访问刷新,否则立即刷新

但是新版无论是否进行notify,都会下轮访问才进行刷新

也就是说内部修改变量已经无法触发刷新了

新版则是收集dep之后,一旦网页访问compute函数,则同时对所有函数的user watch收集的dep也进行一次依赖响应

来让依赖也拿到渲染watch

一旦对其变量进行修改

则变量会对user watch做一个dirty处理

然后触发渲染watch刷新

渲染watch获取computed属性,触发重新计算值

而旧版的逻辑则是

一旦变量更新通知user watch,获取值之后,再由user watch通知渲染watch进行更新

```javascript
Watcher.prototype.update = function update () {
    var this$1 = this;

/* istanbul ignore else */
if (this.computed) {
    // A computed property watcher has two modes: lazy and activated.
    // It initializes as lazy by default, and only becomes activated when
    // it is depended on by at least one subscriber, which is typically
    // another computed property or a component's render function.
    if (this.dep.subs.length === 0) {
      // In lazy mode, we don't want to perform computations until necessary,
      // so we simply mark the watcher as dirty. The actual computation is
      // performed just-in-time in this.evaluate() when the computed property
      // is accessed.
      this.dirty = true;
    } else {
      // In activated mode, we want to proactively perform the computation
      // but only notify our subscribers when the value has indeed changed.
      this.getAndInvoke(function () {
      this$1.dep.notify();
      });
    }
} else if (this.sync) {
    this.run();
} else {
    queueWatcher(this);
}
};
```

黎辰辰 发表于 2022-1-9 13:47:19

:):lol:loveliness:
页: [1]
查看完整版本: vue计算函数新旧变化