简体   繁体   English

是什么导致 Vue 计算属性被计算?

[英]What's causing the Vue computed property to be computed?

My understanding of computed properties is that if the computed property is not used in the template it's not supposed to be computed.我对计算属性的理解是,如果模板中没有使用计算属性,则不应该计算它。 However, when there is a watcher for a computed property, this computed property is evaluated.但是,当有计算属性的观察者时,会评估此计算属性。

I understand it's not desired application architecture, but my question is if the fact that it's working this way is a desired Vue behaviour or some side-effect of how things are implemented right now and can change in future releases?我知道这不是所需的应用程序架构,但我的问题是,它以这种方式工作的事实是否是所需的 Vue 行为,或者是现在实现事物的方式的一些副作用,并且可以在未来的版本中改变?

Or to put the question in other words: Should the computed property be evaluated if it's not used in the template and it has no other explicit getter in the codebase, except a watcher?或者换句话说:如果计算属性没有在模板中使用并且在代码库中除了观察者之外没有其他显式getter,是否应该评估计算属性?

Example:例子:

<template>
  <div>
        <button @click="counter++">+1</button>
        {{ counter }}
  </div>
</template>

<script>
export default {
  name: "Main",
  data() {
    return {
      counter: 0,
    };
  },
  computed: {
    notUsedInTemplate() {
      console.log("notUsedInTemplate computed called");
      return this.counter + 1;
    },
  },
  watch: {
    notUsedInTemplate() {
      console.log("notUsedInTemplate watch called");
    },
  },
};
</script>

Link to sandbox: https://codesandbox.io/s/computed-sandbox-ru3n3?file=/src/components/Main.vue:0-818沙盒链接: https ://codesandbox.io/s/computed-sandbox-ru3n3?file=/src/components/Main.vue:0-818

if the computed property is not used in the template it's not supposed to be computed如果模板中未使用计算属性,则不应计算它

...is not correct. ...是不正确的。 Correct statement is:正确的说法是:

if the computed property is not used (anywhere) it's not supposed to be evaluated如果计算的属性没有被使用(在任何地方),它不应该被评估

Using watch evaluates the property.使用watch评估属性。 In fact watch is very similar to template re-rendering (In vue 3 re-rendering is in fact little special watchEffect )实际上watch和模板重渲染非常相似(在 vue 3 中重渲染其实是一点特殊的 watchEffect

Because to watch (anything):因为要看(任何东西):

  1. Vue 1st needs to run the code - in this case notUsedInTemplate getter - to find out what reactive data it is accessing (so this.counter is tracked as dependency) Vue 1st 需要运行代码 - 在本例中notUsedInTemplate getter - 以找出它正在访问的反应数据(因此this.counter被跟踪为依赖项)
  2. When this.counter changes, watcher runs the notUsedInTemplate getter again so it can compare new value to previous onethis.counter改变时,观察者再次运行notUsedInTemplate getter,以便它可以将新值与前一个值进行比较
  3. If value changed, it runs the callback (which is logging in your example)如果值更改,它将运行回调(在您的示例中记录)

So to answer the questions:所以回答问题:

  1. yes this is desired behavior as your watcher is not tracking changes of notUsedInTemplate computed property but underlying data it uses to compute it's value是的,这是期望的行为,因为您的观察者没有跟踪notUsedInTemplate计算属性的更改,而是用于计算其值的基础数据
  2. Watcher is accessing the computed property, there is no need to use it anywhere else Watcher 正在访问计算属性,无需在其他任何地方使用它

OK, more details WHY this works this way好的,更多细节为什么这样工作

Vue reactivity has always 2 phases: Vue 反应性总是有两个阶段:

  1. phase 1 - run the code (be it template or watch expression/fn ) and collect all dependencies (eg any reactive data the code "touched")阶段 1 - 运行代码(无论是模板还是监视表达式/fn )并收集所有依赖项(例如,代码“触及”的任何反应数据)
  2. phase 2 - track the dependencies.第 2 阶段 - 跟踪依赖关系。 If any dependency changes, re-run callback (or render function)如果任何依赖项发生变化,请重新运行回调(或渲染函数)

See this chapter in the docs - How Changes Are Tracked - the example is explicitly mentioning only template re-rendering (which uses watcher created by Vue itself) but all of this applies to all watchers including those created by the user请参阅文档中的这一章 - How Changes Are Tracked - 该示例明确提到仅模板重新渲染(它使用由 Vue 本身创建的观察者),但所有这些都适用于所有观察者,包括由用户创建的观察者

You are right about the computed property.您对计算属性是正确的。 Anything in the computed property will attach to vue instance and accessible in the template.计算属性中的任何内容都将附加到vue实例并在模板中访问。

So, if it not used in template, it should not be in computed.所以,如果它没有在模板中使用,它不应该在计算中。

computed properties are declarative in where as watch is imperative. computed属性是声明性的,因为watch是必要的。

computed: {
// a computed getter
reversedMessage: function () {
  // `this` points to the vm instance
  return this.message.split('').reverse().join('')
 }
}

And the best part is that we've created this dependency relationship declaratively: the computed getter function has no side effects, which makes it easier to test and understand.最好的部分是我们以声明方式创建了这种依赖关系:计算的 getter 函数没有副作用,这使得测试和理解更容易。

watch are functions that looks for changes and update the value. watch 是查找更改并更新值的函数。

watch: {
firstName: function (val) {
  this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
  this.fullName = this.firstName + ' ' + val
 }
}

By using computed getter property you are just making it easy for vue to track the changes and update in a declarative way, however you can do the same wit watch but it is imperative and vue need to look for changes and each changes required that function call to be trigger and later executing that function.通过使用计算的 getter 属性,您只是使vue可以轻松地以声明性方式跟踪更改和更新,但是您可以执行相同的 wit watch ,但它是必要的,并且 vue 需要查找更改,并且每个更改都需要函数调用被触发并稍后执行该功能。

more info更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM