ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

搞明白Vue什时候该用computed和watch

2021-11-12 23:33:15  阅读:130  来源: 互联网

标签:Vue return computed productList watch 计算 属性


Vue框架中的两大重要特性computed和watch,它们之前有相似的地方,那么今天我们来说说为什么要有computed和watch?以及它们的使用场景?什么时候用computed?什么时候用watch?它们之间有什么差别呢?请看今天的文章

为什么有计算属性computed

在Vue中,我们可以轻松的实现数据到DOM映射,使用模板内的表达式也很方便,但如果在模板内写入太多的逻辑的话就会让模板难以维护。

<template>
  <div :title="msg">
    {{ msg }}
    {{ msg.length }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: 'Hello World',
    }
  },
}
</script>

比如我们有一个商品列表,我们通过商品的数量来显示不同的状态信息,请看下面的例子:

<template>
  <div class="status">
    {{ productList.length > 0 ? '有货' : '商品暂时无货'}}
  </div>
</template>

<script>
export default {
  data() {
    return {
      productList: [{
        title: 'JS 高级编程',
      }],
    }
  },
}
</script>

此时,模板已经不再是简单的了,我们必须得看一下模板内的表达式才能知道它的状态是取决于productList.length。那么如果在模板中有多个地方需要同样状态,我们就必须写多份同样的代码,这样模板就会变得更加的糟糕了。

所以,当我们需要处理一些响应式数据的复杂逻辑时,我们就应该去使用计算属性computed。看下面的例子:

<template>
  <div class="status">
    {{ productStatus }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      productList: [{
        title: 'JS 高级编程',
      }],
    }
  },
  computed: {
    productStatus() {
      return this.productList.length > 0 ? '有货' : '商品暂时无货'
    },
  },
}
</script>

这里我们声明了一个计算属性productStatus

如果我们去更改productList数组的值,那么将会看到productStatus也会相应的进行修改。

我们可以像绑定普通属性一样将计算属性绑定到模板中。Vue在内部知道productStatus依赖于productList,所以当productList发生变化时,所有依赖productStatus的绑定也都会更新。最巧妙的是我们已经通过声明的方式创建了这个依赖方式,而且计算属性的getter函数没有副作用,使得更加容易测试。

计算属性 VS 方法

上面的代码我们也可以通过方法的形式来实现它,例如:

<template>
  <div class="status">
    {{ getProductStatus() }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      productList: [{
        title: 'JS 高级编程',
      }],
    }
  },
  methods: {
    getProductStatus() {
      return this.productList.length > 0 ? '有货' : '商品暂时无货'
    },
  },
}
</script>

我们将相同的逻辑定义为一个函数,而不是计算属性。可以看到两种方式实现的结果是完全相同的。那么有什么不同呢?

重要的来了下面请认真看,不同的地方是:

计算属性是基于响应依赖关系缓存的,计算属性只有在响应式依赖发生改变时才会重新求值,也就是说如果productList永远不发生改变的话,那么每次访问上面的productStatus计算属性都会返回之前计算好的结果,而不必再次去执行函数进行运算。也就是说计算属性会有缓存数据的功能。

比如下面的代码的计算属性将永远不会更新,因为 Date.now () 不是响应式依赖:

computed: {
  now() {
    return Date.now()
  }
}

相比计算属性,使用方法的方式,每当触发重新渲染的时候,方法就总会再次被执行。如果模板中有N个方法调用,那么将调用N次。

那么计算属性的缓存有什么优势呢?

假设我们有一个性能开销比较大的计算属性 list,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 list。如果没有缓存,我们将不可避免的多次执行 list 的 getter!

这样在性能上就会好很多。

计算属性的 Setter

计算属性默认只有 getter,不过也可以去设置一个 setter,像下面一样:

// ...
computed: {
  fullName: {
    // getter
    get() {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set(newValue) {
      const names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

当我们运行 this.fullName = '小 帅' 时,setter 会被调用,this.firstNamethis.lastName 也会相应地被更新。

这个setter我还很少的在项目中会使用得到,大家会在什么时候能够用到呢,欢迎提供素材。

Watch

计算属性在大多数时候其实已经能够满足我们的使用了,但Vue还是给我们提供了一个更加自由的监听数据变化的方式,那就是watch。

那么什么时候去用watch呢?

根据Vue官方文档的定义

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

经过改良的例子,假设我们要根据关键字去查询商品的列表

<div id="watch-example">
  <p>
    请输入商品的名称
    <input v-model="keywords" />
  </p>
  <p v-if="getting">数据获取中..</p>
  <p v-else v-for="item in productList">{{ item.title }}</p>
</div>
<script>
  const watchExampleVM = Vue.createApp({
    data() {
      return {
        keywords: '',
        getting: false,
        productList: []
      }
    },
    watch: {
      // 如果keywords发生改变, 这个函数就会触发
      keywords(newKeywords, oldKeywords) {
        if (newKeywords.indexOf('?') > -1) {
          this.getAnswer()
        }
      }
    },
    methods: {
      getProductList() {
        this.getting = true;
        axios
          .get('/api/products')
          .then(response => {
            this.productList = response.data
          })
       	  .finally(() => {
          	this.getting = false;
          })
      }
    }
  }).mount('#watch-example')
</script>

在这个例子中,使用 watch 可以让我们调用异步的API来获取数据,并用getting属性来控制数据状态,这些使用计算属性是无法做到的。

滥用Watch

Vue提供的Watch可以让我们监听任何响应数据的变化,当我们有一些数据需要随着其他数据的变化而变化时,很容易去使用watch,然而其实更好的方式是去使用声明式的计算属性,而不是命令式的 watch 回调,请体会下面的例子:

<div id="demo">{{ fullName }}</div>
const vm = Vue.createApp({
  data() {
    return {
      firstName: 'Foo',
      lastName: 'Bar',
      fullName: 'Foo Bar'
    }
  },
  watch: {
    firstName(val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName(val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
}).mount('#demo')

上面代码是命令式且重复的。与计算属性的版本进行比较:

const vm = Vue.createApp({
  data() {
    return {
      firstName: 'Foo',
      lastName: 'Bar'
    }
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName
    }
  }
}).mount('#demo')

通过上面的比较发现,计算属性就好很多。

最后

参考Vue官方文档:计算属性和侦听器

一起学习更多前端知识,微信搜索【小帅的编程笔记】,每天更新

标签:Vue,return,computed,productList,watch,计算,属性
来源: https://blog.csdn.net/cmdfas/article/details/121298142

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有