Vue中 computed 和 watch 区别及应用场景详解

简介: Vue中 computed 和 watch 区别及应用场景详解

在 vue 的项目中,我们时常会需要对 data 的改变做出处理,这时候就需要用到 watch 和 computed 这两个属性。既然都是数值改变触发改变的属性,他们之间又有什么异同呢?

1. 计算属性 computed

特点:

支持缓存,只有依赖数据发生改变,才会重新进行计算;

不支持异步,当 computed 内有异步操作时无效,无法监听数据的变化;

computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的。也就是基于 data 中声明过或者父组件传递的 props 中的数据通过计算得到的值;

如果一个属性是由其他属性计算而来的,这个属性依赖其他属性 是一个多对一或者一对一,一般用computed;

如果 computed 属性值是函数,那么默认会走 get 方法,函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个 set 方法,当数据变化时,调用 set 方法;

<template>
  <div>
    <el-input v-model="firstText"></el-input>
    <el-input v-model="lastText"></el-input>
    <el-input v-model="mergeText1"></el-input>
    <el-input v-model="mergeText2"></el-input>
  </div>
</template>
<script>
export default {
  data() {
    return {
      firstText:'hello',
      lastText:'world',
    };
  },
  computed:{
    mergeText1(){
      return this.firstText + ' ' + this.lastText;
    },
    mergeText2:{  /* 通过mergeText2反向赋值给 firstText和lastText */
      // getter
      get() {  // 回调函数 当需要读取当前属性值是执行,根据相关数据计算并返回当前属性的值
        return `${this.firstText} ${this.lastText}`;
      },
      // setter
      set(val) {  //监视当前属性值的变化,当属性值发生变化时执行,更新相关的属性数据,val就是fullName的最新属性值
        const names = val.split(' ');
        console.log(names);
        this.firstText = names[0];
        this.lastText = names[names.length - 1];
      }
    }
  },
};
</script>

优点:

当改变 data 变量值时,整个应用会重新渲染,vue 会被数据重新渲染到 dom 中。这时,如果我们使用 names ,随着渲染,方法也会被调用,而 computed 不会重新进行计算,从而性能开销比较小。当新的值需要大量计算才能得到,缓存的意义就非常大;

如果 computed 所依赖的数据发生改变时,计算属性才会重新计算,并进行缓存;当改变其他数据时,computed 属性 并不会重新计算,从而提升性能;

当拿到的值需要进行一定处理使用时,就可以使用 computed;

应用场景:

2020062310470442.png

2. 侦听属性 watch

特点:

不支持缓存,数据变化,直接会触发相应的操作;

watch 支持异步操作;

监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;

当一个属性发生变化时,需要执行对应的操作,一对多;

监听数据必须是 data 中声明过或者父组件传递过来的 props 中的数据。当数据变化时触发其他操作,函数有两个参数:

immediate:组件加载立即触发回调函数执行;

deep: 深度监听;为了发现对象内部值的变化,复杂类型的数据时使用,例如:数组中的对象内容的改变,注意:监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到;

注:当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的,这是和 computed 最大的区别。

2.1 一般用法,监听单个变量或一个数组

<template>
  <div>
    <el-input v-model="firstText"></el-input>
    <el-input v-model="lastText"></el-input>
    <el-input v-model="mergeText"></el-input>
  </div>
</template>
<script>
export default {
  data() {
    return {
      firstText:'hello',
      lastText:'world',
      mergeText:'',
    };
  },
  watch:{
    // 监听当firstText的值变化,触发此事件,改变mergeText的值
    firstText(newText,oldText){
      console.log(newText, oldText);
      this.mergeText = newText + ' ' + this.lastText;
    }
  },
};
</script>

2.2 监听简单数据类型

<template>
  <div>
    <el-input v-model="mergeText"></el-input>
  </div>
</template>
<script>
export default {
  data() {
    return {
      mergeText:'',
    };
  },
  watch:{
    // mergeText值变化即触发
    mergeText(newval,oldVal){
      console.log(this.mergeText,newval,oldVal);
    }
  },
};
</script>

2.3 监听复杂数据(深度监听 deep)

不使用 deep 时,当我们改变 obj.a 的值时,watch 不能监听到数据变化,默认情况下,handler 只监听属性引用的变化,也就是只监听了一层,但改对象内部的属性是监听不到的。


immerdiate 属性: 通过声明 immediate 选项为 true,可以立即执行一次 handler。

<template>
  <div>
    <el-input v-model="obj.text"></el-input>
  </div>
</template>
<script>
export default {
  data() {
    return {
      obj:{
        text:'hello'
      }
    };
  },
  watch:{
    // 监听对象obj的变化
    obj:{
      handler (newVal,oldval) {
        console.log(newVal,oldval)
      },
      deep: true,
      immediate: true
    }
  },
};
</script>

通过使用 deep: true 进行深入观察,我们监听 obj,会把 obj 下面的属性层层遍历,都加上监听事件,这样做性能开销也会变大,只要修改 obj 中任意属性值,都会触发 handler,那么如何优化性能呢?

可以直接对用对象 . 属性的方法拿到属性

<template>
  <div>
    <el-input v-model="obj.text"></el-input>
  </div>
</template>
<script>
export default {
  data() {
    return {
      obj:{
        text:'hello',
      }
    };
  },
  watch:{
    // 监听对象单个属性text
    'obj.text':{
      handler (newVal,oldval) {
        console.log(newVal,oldval)
      },
      immediate: true, // 该属性会先执行一次handler
    }
  },
};
</script>

注意事项:

watch 中的函数是不需要调用的,只要函数所依赖的属性发生了改变 那么相对应的函数就会执行;

watch 中的函数会有2个参数 一个是新值,一个是旧值;

watch 默认情况下无法监听对象的改变,如果需要进行监听则需要进行深度监听 深度监听需要配置 handler 函数以及 deep 为true。(因为它只会监听对象的地址是否发生了改变,而值是不会监听的);

watch 默认情况下第一次的时候不会去做监听,如果需要在第一次加载的时候也需要去做监听的话需要设置 immediate:true;

watch 在特殊情况下是无法监听到数组的变化:

通过下标来更改数组中的数据;

通过 length 来改变数组的长度;

解决方案:

通过 Vue 实例方法 set 进行设置 $set( target, propertyName/index, value);
参数:target {Object | Array} , propertyName/index {string | number}, value {any}
this.$set(this.arr,0,100);
通过 splice 来数组清空 $delete( target, propertyName/index )
参数:target {Object | Array} , propertyName/index {string | number}
this.$delete(this.arr,0)
  1. 深度监听对应的函数名必须为 handler ,否则无效果,因为 watche r里面对应的是对 handler 的调用

应用场景:

2020062310470442.png

3. 方法 methods

methods 跟前面的都不一样,我们通常在这里写入方法,只要调用就会重新执行一次,相应的有一些触发条件,在某些时候 methods 和 computed 看不出来具体的差别,但是一旦在运算量比较复杂的页面中,就会体现出不一样。

注意:computed 是具有缓存的,这就意味着只要计算属性的依赖没有进行相应的数据更新,那么 computed 会直接从缓存中获取值,多次访问都会返回之前的计算结果。

4. 总结

在 computed 和 watch 方面,一个是计算,一个是观察,在语义上是有区别的。

计算是通过变量计算来得出数据,而观察是观察一个特定的值,根据被观察者的变动进行相应的变化,在特定的场景下不能相互混用,所以还是需要注意 api 运用的合理性和语义性。





相关文章
|
12天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
12天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
12天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
25天前
|
JavaScript 搜索推荐 前端开发
Vue SSR 预渲染的广泛应用场景及其优势
【10月更文挑战第23天】Vue SSR 预渲染技术在众多领域都有着广泛的应用价值,可以显著提升网站的性能、用户体验和搜索引擎优化效果。随着技术的不断发展和完善,其应用场景还将不断拓展和深化
43 2
|
1月前
|
缓存 JavaScript
Vue 中 computed 与 method 的区别
【10月更文挑战第15天】computed 和 method 是 Vue 中两个重要的选项,它们在功能和特点上存在着明显的区别。理解并合理运用它们的区别,可以帮助我们构建更高效、更具可维护性的 Vue 应用。在实际开发中,要根据具体情况灵活选择使用,以满足不同的需求。
19 2
|
27天前
|
缓存 JavaScript 数据管理
优化 Vue 应用中的性能
【10月更文挑战第22天】优化 Vue 应用性能需要综合考虑多个方面,从数据管理、组件化、虚拟 DOM 操作、网络请求、代码结构等多方面入手,不断进行优化和改进,以提供更流畅的用户体验。同时,要根据具体的应用场景和需求,选择合适的优化策略,确保性能优化的效果和可行性。
|
JavaScript 测试技术 容器
Vue2+VueRouter2+webpack 构建项目
1). 安装Node环境和npm包管理工具 检测版本 node -v npm -v 图1.png 2). 安装vue-cli(vue脚手架) npm install -g vue-cli --registry=https://registry.
1053 0
|
6天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
vue学习第四章
|
6天前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
vue学习第九章(v-model)
|
6天前
|
JavaScript 前端开发 开发者
vue学习第十章(组件开发)
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文深入讲解Vue组件的基本使用、全局与局部组件、父子组件通信及数据传递等内容,适合前端开发者学习参考。持续更新中,期待您的关注!🎉🎉🎉
vue学习第十章(组件开发)
下一篇
无影云桌面