vue中的computed和watch到底有什么不同?

如题,在vue.js官方文档中看到computed和watch获取全名的一个例子:

var var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})
var var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

菜鸟表示不太懂他们之间的区别,难道watch就不可以像computed那样来获取吗?

阅读 62.6k
18 个回答

用computed代码写的少,没什么主要区别

我觉得还是有区别的,而且两种应用的情形应该区分开。

计算属性是计算属性,侦听器watch是侦听器watch。

计算属性顾名思义就是通过其他变量计算得来的另一个属性,fullName在它所依赖firstName,lastName这两个变量变化时重新计算自己的值。

另外,计算属性具有缓存。计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 lastName和firstName都没有发生改变,多次访问 fullName计算属性会立即返回之前的计算结果,而不必再次执行函数。

而侦听器watch是侦听一个特定的值,当该值变化时执行特定的函数。例如分页组件中,我们可以监听当前页码,当页码变化时执行对应的获取数据的函数。

可以再详细的查看一下文档:https://cn.vuejs.org/v2/guide...

①从属性名上,computed是计算属性,也就是依赖其它的属性计算所得出最后的值。watch是去监听一个值的变化,然后执行相对应的函数。
②从实现上,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算。watch在每次监听的值变化时,都会执行回调。其实从这一点来看,都是在依赖的值变化之后,去执行回调。很多功能本来就很多属性都可以用,只不过有更适合的。如果一个值依赖多个属性(多对一),用computed肯定是更加方便的。如果一个值变化后会引起一系列操作,或者一个值变化会引起一系列值的变化(一对多),用watch更加方便一些。
watch的回调里面会传入监听属性的新旧值,通过这两个值可以做一些特定的操作。computed通常就是简单的计算。
watchcomputed并没有哪个更底层,watch内部调用的是vm.$watch,它们的共同之处就是每个定义的属性都单独建立了一个Watcher对象。

并不是,作用不一样。

computed是用于定义基于数据之上的数据

而watch是你想在某个数据变化时做一些事情,如果做的事情是更新其他数据,那其实与把这个要更新的数据项定义成computed是一样的,这个时候用computed更有可读性,虽然技术上讲watch也可以实现。

但你也可以在被watch的数据变化时做其他事情啊,比如调用一个方法,这个是computed做不到也不应该做的。

总结:

  • 1.如果一个数据依赖于其他数据,那么把这个数据设计为computed的

  • 2.如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化

区别:

  1. computed会产生新的属性,产生的新的属性与data中原有的属性功能没有区别.用法一样;watch不会产生新的属性.
  2. computed会在vue实例化过程中执行一次(前提是这个计算属性在template有用到,如果没有用到,这个computed永远不会执行,包括vue初始化时);watch在vue初始化时,不会执行.

开发时选用哪一个:想得到某个属性变化时产生的结果用computed.某个属性变化时产生的影响用watch.一个侧重结果(值),一个侧重影响(过程).

在写法上有一个区别。computed返回state处理后结果,watch是赋值行为,修改state。

正如文档建议说 执行异步操作或开销较大的操作时使用watch。

我理解是

  1. 执行异步操作不能串行返回结果,使用watch。

  2. 开销较大的操作,避免堵塞主线程,使用watch。

  3. 简单且串行返回的,使用computed

那么,用watch的时候更多的就去监听props的变化,而computed就用来计算data的值,感觉这样更好些~~~

computed属性强调计算,比若说c = a + b, b 是外界传过来不断变化的,而你要显示到页面上的是C,那么就建议用computed
watch属性强调自身值得改变前后的动作,所以才有回调xxx(newVal,oldVal)

更具可读性,以及通常来说更少的代码。

watch可以监听某个data变化而做出不同的反应 比如可以在data到一定程度的时候关闭页面 computed就做不到这一点

简单来看computed是基于缓存进行的,watch等于一个函数。个人觉得会用就行了,具体区别移驾具体区别

觉得还是计算属性用的能广泛一些吧

watch应该是更底层的实现,computed在其上创建,每更新任何一个属性都会触发这个属性的watch,以及一次computed

新手上路,请多包涵

watch侧重监听某一个属性,computed侧重结果

新手上路,请多包涵

computed是用data已经申明的变量可以计算出来的另一个变量用来渲染页面比较合适方便,而watch适合监听某个data中的变量来操作一些逻辑行为比较合适,比如监听某个变量改变然后发起异步请求。

//属性 y = a*b*c;
html: {{a}} * {{b}} * {{c}} = {{y}}

如果用计算属性写:
y () {
    return a*b*c
}

如果用watch:
a (val) {
    this.y = val*this.b*this.c
}
b (val) {
    this.y = this.a*val*this.c
}
C (val) {
    this.y = this.a*this.b*val
}
`
新手上路,请多包涵

使用场景有细分
computed: 对绑定的值有依赖,每次操作依赖的值没有发生改变时,则只取第一次的值,具有缓存特性;一般用于纯粹的取值计算
watch:侦听值前后变化的状态,每次操作无论值是否有变化,都会执行定义函数体;一般用于数据变化时执行异步操作或开销比较大的操作

对于method方法,每次页面发生渲染,都会被重新调用。点击button,触发changeSum事件,让add增加,页面重新渲染,sum也会被调用,打印出来“sum is changing”

computed可以减少这种无意义的计算,sumInComputed只依赖于numa和numb,只要这两个没有发生变化,即使页面重新渲染,sumInComputed的方法也不会调用。若在changeSum方法中加入this.numa++;或this.numb--; 只要numa或numb发生变化,sumInComputed的方法被调用,打印出来"sumInComputed is changing!"

watch 直接监测一个值的变化情况,不会像computed检测依赖。若在changeSum中加入this.numa++; this.numb--; 和this.sumWatch = this.numa + this.numb; sumWatch的值没有发生变化,哪怕numa和numb的值已经发生变化,sumWatch的方法也不会被调用。

<template>
  <div>
    <div>add is: {{add}}</div>
    <div>sumInComputed is: {{sumInComputed}}</div>
    <span>the sum is: {{sum()}}</span>
    <button @click="changeSum">changeSum</button>
  </div>
</template>
<script>
  data () {
      numa: 3,
      numb: 4,
      sumWatch: 0
  },
  computed: {
    sumInComputed: function () {
      console.log("sumInComputed is changing!");
      return this.numa + this.numb;
    }
  },
  watch: {
    sumWatch: function (val,oldVal) {
      console.log("sumWatch is changing!");
    }
  },
  methods: {
    changeSum () {
      this.add++;
      // this.numa++;
      // this.numb--;
      // this.sumWatch = this.numa + this.numb;
    },
    sum () {
      console.log(" sum is changing!");
      return this.numa + this.numb;
    }
  }
</script>
推荐问题
宣传栏