vue data改变时,computed是否立刻改变,还是在读取computed中的属性时才改变?

读vue源码时,遇到了一个问题
访问computed中的属性时,这是其get触发的方法

if (watcher) {
   if (watcher.dirty) {
      watcher.evaluate()
   }
   if (Dep.target) {
      watcher.depend()
   }
   return watcher.value
}

只有computedWatcher中的dirty为true时,才执行computed内的函数,此时访问了data中的数据,与computed建立了依赖联系,执行完dirty属性=false
当我改变相关data中属性的值时,data的set执行的只是

dep.notify()
---
notify () {
    const subs = this.subs.slice()
    for (let i = 0, l = subs.length; i < l; i++) {
      subs[i].update()
    }
---
update () {
    this.dirty = true
    //...
  }

至此,并没有去计算computed中最新的值,而只是把watcher中的dirty设为true,当下次访问这个computed属性时,就会重新计算这个值
从我分析来看,当我在改变data中的值时,我此时并没有更新computed中的值,而我需要访问computed中的属性时才会更新。
但是从实践来看,并不是我想的这样

        data: {
          a: 1,
        },
        computed: {
            update_a() {
                return this.a + '---'
            }
        },
        methods: {
            sayHello() {
                this.a++;
                console.log(this)
            }
        }
    ------ 结果 --- 
    //Vue {a:2, update_a: 2---} 

为什么?

阅读 5.5k
1 个回答

你的理解是对的,但是验证的时候犯错了。你打印this之后在控制台查看到应该是像下面这样值是省略的,必须点开才能看到具体是什么值。屏幕快照 2019-12-26 下午5.52.15.png
但当你一打开的时候其实就等同于访问了该属性,也就触发了getter,所以更新了值。其实你的想法是对的,但你应该像下面这么验证你的想法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <button @click="increment">increment</button>
        <p>{{count}}</p>
        <button @click="onClick">log this</button>
    </div>
    <script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js"></script>
    <script>
        new Vue({
            el: '#app',
            data: {
                count: 1,
            },
            computed: {
                msg() {
                    console.log('update computed')
                    return 'computed_' + this.count;
                }
            },
            methods: {
                increment() {
                    this.count++;
                },
                onClick() {
                    console.log(this)
                }
            },
        })
    </script>
</body>
</html>

我的computed msg依赖于count,并且我在更新computed时打印了一句话,你可以看看当count增加时会不会输出log就知道是否是立即更新的。当展开this中的msg属性时你会发现控制台输出了log。证明确实只有在访问属性时才会触发getter

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题