Vue—计算属性和监听属性 computed和watch的区别

简介: Vue—计算属性和监听属性 computed和watch的区别

@TOC

计算属性

为什么需要计算属性?

生活中常常会使用到各种复杂逻辑计算,若全部放在逻辑表达式里,会让模板过于繁重且难以维护,于是我们需要把一些响应式数据的复杂逻辑放在专门的计算模块中。

基本使用

下面是一个简单的例子,其首先在data中声明author,author中包含name和books,然后利用计算属性判断books属性长度是否大于0,若大于0则输出其值。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="computed-basics" class="demo">
    <p>Has published books:</p>
    <span>{{ publishedBooksMessage }}</span>
  </div>
<script>
Vue.createApp({
  data() {
    return {
      author: {
        name: 'John Doe',
        books: ['Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery']
      }
    }
  },
  computed: {
    // a computed getter
    publishedBooksMessage() {
      // `this` points to the vm instance
      if(this.author.books.length > 0)
        return 'Yes!'+this.author.books;
      else
        return 'No'
    }
  }
}).mount('#computed-basics')
</script>
</body>
</html>

计算属性的关键字为computed,其首先声明publishedBooksMessage函数,你可以像普通属性一样将数据绑定到模板中的计算属性。Vue 知道 vm.publishedBookMessage 依赖于 vm.author.books,因此当 vm.author.books 发生改变时,所有依赖 vm.publishedBookMessage 的绑定也会更新。

computed和methods区别

可以看到computed可以达到和methods同样的效果。都可以通过在表达式中调用方法。

但是不同的是,computed是基于它的响应依赖关系缓存,computed是属性调用,而methods是函数调用,

通俗的来说就是,计算属性(computed)在系统刚运行的时候调用一次,之后只要值不改变,dom中的值不再去调用函数取值,而是从缓存中获取,速度会很快,,比如上例中,每次author.books发生变化时,都会调用一次计算属性。而方法选项methods仅仅刚加载时调用一次,不管值有没有改变,一旦dom中要取值,则会再次调用方法

下面的例子可以帮助理解不同。

<body>
  <div id="computed-basics" class="demo">
    <h1>{{message}}</h1>
    <p class="test2-1">{{methodTest()}}</p>
    <p class="test2-2">{{methodTest()}}</p>
    <p class="test2-3">{{methodTest()}}</p>
    <p class="test3-1">{{computedTest}}</p>
    <p class="test3-2">{{computedTest}}</p>
  </div>
<script>
Vue.createApp({
  data() {
    return {
      message: '我是消息,'
    }
  },
  methods: {
        methodTest() {
            return this.message + '现在我用的是methods'
        }
    },
  computed: {
    // a computed getter
    computedTest() {
            return this.message + '现在我用的是computed'
        }
  }
}).mount('#computed-basics')
</script>
</body>
</html>

methods定义的方法是以函数调用的形式来访问的

test2-1,test2-2,test2-3是反复地将methodTest方法运行了三遍,如果我们碰到一个场景,需要1000个methodTest的返回值,那么毫无疑问,这势必造成大量的浪费

更恐怖的是,如果你更改了message的值,那么这1000个methodTest方法每一个又会重新计算。

computed依赖于data中的数据,只有在它的相关依赖数据发生改变时才会重新求值,如上例,在Vue实例化的时候,computed定义computedTest方法会做一次计算,返回一个值

在随后的代码编写中,只要computedTest方法依赖的message数据不发生改变,computedTest方法是不会重新计算的

也就是说test3-1,test3-2是直接拿到了返回值,并不是computedTest方法重新计算的结果,而是直接从缓存拿来的结果

在使用时:对于任何复杂逻辑和一些重复的函数,你都应当使用计算属性computed,可以大量节省资源。

计算属性的 Setter

计算属性默认只有 getter,不过在需要时你也可以提供一个 setter。

其中getter方法用于获取,setter方法用于修改。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="app-test" class="demo">
  </div>
  <script>
    const app = {
      data() {
        return {
          name: 'Google',
          url: 'http://www.google.com'
        }
      },
      computed: {
        site: {
          // getter
          get: function () {
            return this.name + ' ' + this.url
          },
          // setter
          set: function (newValue) {
            var names = newValue.split(' ')
            this.name = names[0]
            this.url = names[names.length - 1]
          }
        }
      }
    }
    vm = Vue.createApp(app).mount('#app-test')
    document.write('name: ' + vm.name);
    document.write('<br>');
    document.write('url: ' + vm.url);
    document.write('<br>------ 更新数据 ------<br>');
    // 调用 setter, vm.name 和 vm.url 也会被对应更新
    vm.site = '百度 https://www.baidu.com';
    document.write('name: ' + vm.name);
    document.write('<br>');
    document.write('url: ' + vm.url);
    </script>
</body>
</html>

当调用 setter对vm.site进行修改后, vm.name 和 vm.url 也会被对应更新

监听属性

当需要在数据变化时执行异步或开销较大的操作时, Vue 通过 监听(watch )选项提供了一个更通用的方法来响应数据的变化。

基本使用

通过使用 watch 实现计数器,为counter添加监听,每次触发点击事件时,运行function(counter),跳出提示。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id = "app-test">
  <p style = "font-size:25px;">计数器: {{ counter }}</p>
  <button @click = "counter++" style = "font-size:25px;">点我</button>
</div>
    <script>
      const app = {
        data() {
          return {
            counter: 1
          }
        }
      }
      vm = Vue.createApp(app).mount('#app-test')
      vm.$watch('counter', 
      function(counter) {
        alert('计数器值变为 :' + counter + '!');
      });
      </script>
</body>
</html>

在这里插入图片描述

更多关于watch的可以查阅官方文档

computed和watch的区别

使用 watch 选项允许我们执行异步操作 (访问一个 API),并设置一个执行该操作的条件。这些都是computed属性无法做到的。如下面这个例子

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Vue 测试实例</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="watch-example" class="demo">
    <p>
      Ask a yes/no question:
      <input v-model="question" />
    </p>
    <p>{{ answer }}</p>
  </div>
  <style>
    .demo {
      font-family: sans-serif;
      border: 1px solid #eee;
      border-radius: 2px;
      padding: 20px 30px;
      margin-top: 1em;
      margin-bottom: 40px;
      user-select: none;
      overflow-x: auto;
    }
  </style>
  <!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
  <!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
  <script>
    const watchExampleVM = Vue.createApp({
      data() {
        return {
          question: '',
          answer: 'Questions usually contain a question mark. ;-)'
        }
      },
      watch: {
        // whenever question changes, this function will run
        question(newQuestion, oldQuestion) {
          if (newQuestion.indexOf('?') > -1) {
            this.getAnswer()
          }
        }
      },
      methods: {
        getAnswer() {
          this.answer = 'Thinking...'
          axios
            .get('https://yesno.wtf/api')
            .then(response => {
              this.answer = response.data.answer
            })
            .catch(error => {
              this.answer = 'Error! Could not reach the API. ' + error
            })
        }
      }
    }).mount('#watch-example')
  </script>
</body>
</html>

在这里插入图片描述

除上以外,computed和watch的区别主要有:

1、是否调用return:computed中的函数必须要用return返回,watch中的函数不是必须要用return。

2、computed默认第一次加载的时候就开始监听;watch默认第一次加载不做监听,如果需要第一次加载做监听,就必须添加immediate属性,设置为true(immediate:true)

3、使用场景:computed 和 watch 的使用场景并不一样,computed 的话是通过几个数据的变化,来影响一个数据,而 watch,则是可以一个数据的变化,去影响多个数据。

4、是否调用缓存:computed中的函数所依赖的属性没有发生变化,调用时会从缓存中读取(如上文所说),而watch不调用缓存。

相关文章
|
22天前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
101 60
|
1月前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
2月前
|
JavaScript 前端开发 开发者
Vue v-for 进阶指南:in 与 of 的区别及应用场景 | 笔记
Vue.js 中的 v-for 是强大的遍历指令,但其中的 in 和 of 关键字往往被开发者忽视。尽管它们的用法相似,但适用的场景和数据结构却各有不同。本文将详细探讨 v-for 中 in 和 of 的区别、适用场景以及在实际开发中的最佳使用时机。通过理解它们的差异,你将能够编写更加高效、简洁的 Vue.js 代码,灵活应对各种数据结构的遍历需求。
112 6
|
2月前
|
缓存 JavaScript
Vue 中 computed 与 method 的区别
【10月更文挑战第15天】computed 和 method 是 Vue 中两个重要的选项,它们在功能和特点上存在着明显的区别。理解并合理运用它们的区别,可以帮助我们构建更高效、更具可维护性的 Vue 应用。在实际开发中,要根据具体情况灵活选择使用,以满足不同的需求。
30 2
|
2月前
|
JavaScript 前端开发 开发者
VUE学习一:初识VUE、指令、动态绑定、计算属性
这篇文章主要介绍了Vue.js的基础知识,包括初识Vue、指令如v-for、v-on的使用、动态属性绑定(v-bind)、计算属性等概念与实践示例。
65 1
|
2月前
|
缓存 JavaScript Serverless
vue中computed计算属性、watch侦听器、methods方法的区别以及用法
vue中computed计算属性、watch侦听器、methods方法的区别以及用法
128 0
|
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.
1059 0
|
25天前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
27天前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
|
1天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。