Vue 2.0学习笔记之Vue中的computed属性


Posted in Javascript onOctober 16, 2017

Vue中的 computed 属性称为 计算属性 。在这一节中,我们学习Vue中的计算属性如何使用?记得在学习Vue的模板相关的知识的时候,知道在模板内可以使用表达式,而且模板内的表达式是非常的便利,但这种遍历是有一定的限制的,它们实际上是用于一些简单的运算。也就是说,如果在模板中放入太多的逻辑会让模板过重而且难以维护。咱们先来看一个示例:

<div id="app">
  <h1>{{ message.split('').reverse().join('') }}</h1>
</div>

在这个示例中,模板不再简单和清晰。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。

这就是对于任何复杂逻辑,你都应当使用 计算属性 的原因。接下来咱们一起来学习Vue中的计算属性。

计算属性可用于快速计算视图( View )中显示的属性。这些计算将被缓存,并且只在需要时更新。

在Vue中有多种方法为视图设置值:

  • 使用指令直接将数据值绑定到视图
  • 使用简单的表达式对内容进行简单的转换
  • 使用过滤器对内容进行简单的转换

除此之外,我们还可以使用计算属性根据数据模型中的值或一组值来计算显示值。

计算属性

计算属性允许我们对指定的视图,复杂的值计算。这些值将绑定到依赖项值,只在需要时更新。

例如,我们可以在数据模型中有一个 results 数组:

data () {
  return {
    results: [
      {
        name: 'English',
        marks: 70
      },
      {
        name: 'Math',
        marks: 80
      },
      {
        name: 'History',
        marks: 90
      }
    ]
  }
}

假设我们想要查看所有主题的总数。我们不能使用 filters 或 expressions 来完成这个任务。

  • filters :用于简单的数据格式,在应用程序的多个位置都需要它
  • expressions :不允许使用流操作或其他复杂的逻辑。他们应该保持简单

这个时候,计算属性就可以派上用场。我们可以向模型中添加一个计算值,如下:

computed: {
  totalMarks: function () {
    let total = 0
    let me = this
    for (let i = 0; i < me.results.length; i++) {
      total += parseInt(me.results[i].marks)
    }
    return total
  }
}

totalMarks 计算属笥使用数组 resultes 的 marks 计算出总值。它只是循环遍历值并返回子总数。

然后,我们可以在视图中显示计算值:

<div id="app">
  <div v-for="subject in results">
    <input v-model="subject.marks">
    <span>Marks for {{ subject.name }}: {{ subject.marks }}</span>
  </div>
  <div>
    Total marks are: {{ totalMarks }}
  </div>
</div>

效果如下:

Vue 2.0学习笔记之Vue中的computed属性

计算属性 vs 方法

我们可以使用Vue中的 method 计算出学科的总分,最终得到的总数结果是相同的。

在上例的基础上,我们把 computed 区块中的 totalMarks 函数整体移到 methods 中。同时在模板中将 {{ totalMarks }} 替换成 {{ totalMarks() }} 。 你最终看到的结果是一样的,如下所示:

let app = new Vue({
 el: '#app',
 data () {
  return {
   results: [
    {
     name: '英语',
     marks: 70
    },
    {
     name: '数学',
     marks: 80
    },
    {
     name: '历史',
     marks: 90
    }
   ]
  }
 },
 methods: {
  totalMarks: function () {
   let total = 0
   let me = this
   for (let i = 0; i < me.results.length; i++) {
    total += parseInt(me.results[i].marks)
   }
   return total
  }
 }
})

虽然这两种方式输出的结果是相同的,但是性能将遭受毁灭性的打击。使用这种方法, totalMarks() 方法在每次页面渲染时都被执行一次(例如,使用每一个 change )。

如果我们有一个计算属性,那么Vue会记住计算的属性所依赖的值(在我们这个示例中,那就是 results )。通过这样做,Vue只有在依赖变化时才可以计算值。否则,将返回以前缓存的值。这也意味着 只要 results 还没有发生改变,多次访问 totalMarks 计算属性会立即返回之前的计算结果,而不必再次执行函数。

上面两个示例也说明,在Vue中 计算属性是基于它们的依赖进行缓存的,而方法是不会基于它们的依赖进行缓存的。从而使用计算属性要比方法性能更好。

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

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

相比之下,每当触发重新渲染时,方法的调用方式将总是再次执行函数。因此,函数必须是一个纯函数。它不能有副作用。输出只能依赖于传递给函数的值。

那么我们为什么需要缓存?假设我们有一个性能开销比较大的的计算属性 A ,它需要遍历一个极大的数组和做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter !如果你不希望有缓存,请用方法来替代。

计算属性的 setter

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

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

效果如下:

Vue 2.0学习笔记之Vue中的computed属性

你在输入框中输入一个 fullName ,然后点击 set 按钮,可以看到对应的效果。你现在再运行 app.fullName="Airen liao" 时,计算属性的 setter 会被调用, app.firstName 和 app.lastName 也相应地会被更新。如下图所示:

Vue 2.0学习笔记之Vue中的computed属性

观察者

虽然计算属性在大多数情况下更合适,但有时候也需要一个自定义的 watcher 。这是为什么Vue通过 watch 选项提供一个更通用的方法,来响应数据的变化。当你想要在数据变化响应时,执行异步操作或开销较大的操作,这是很有用的。

Vue确实提供了一种更通用的方式来观察和响应Vue实例上的数据变动: watch 属性 。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch 。然而,通常更好的想法是使用计算属性而不是命令式的 watch 回调。比如下面的示例:

<div id="app">
  {{ fullName }}
</div>

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

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

let app = new Vue({
  el: '#app',
  data () {
    return {
      firstName: 'Foo',
      lastName: 'Bar'
    }
  },
  computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }
  }
})

在Vue中使用异步计算属性

Vue中的计算属性非常好。它们允许你执行复杂的操作或数据格式,同时最大限度地执行依赖项计算的性能,只在依赖更改时更新视图。但遗憾的是,它们完全是同步的。

值得庆幸的是,有一个插件。使用vue-async-computed 包可以通地将一个 promise 的值绑定到组件属性来创建和使用组件中的异步计算属性。

我们可以在项目的根目录下通过 yarn 或 npm 来安装 vue-async-computed 插件:

# Yarn
$ yarn add vue-async-computed
# NPM
$ npm i vue-async-computed --save

接下来在你的项目中开启这个插件:

// main.js
import Vue from 'vue';
import AsyncComputed from 'vue-async-computed'
import App from 'App.vue';

Vue.use(AsyncComputed);

new Vue({
  el: '#app',
  render: h => h(App)
});

如果你和我一样,对Vue的构建工具不是很熟悉的话,我建议你使用Vue官方提供的构建工具 Vue CLI 。默认情况,它提供了五种模板,你可以根据自己喜欢的方式选择自己需要的模板即可。

确认在项目中引用 vue-async-computed 之后,咱们就可以开始使用这个插件了。使用如何使用这个插件之前,先来简单的了解一些概念。

在Vue中标准计算属性和异步属性之间有一些区别:

  • 异步属性不能有 setter
  • 直到 promise 的 resolve 为止,除非 default 被设置,否则该值为 null

在大多数情况下,你可以将它们视为返回 promise 的计算属性。

<!-- MyComponent.vue -->
<template>
  <!-- 在一两秒后 myResolvedValue将变成"*Fancy* Resolved Value" -->
  <h2>Asynchronous Property {{ myResolvedValue }}</h2>
</template>

<script>
  export default {
    asyncComputed: {
      myResolvedValue () {
        return new Promise((resolve, reject) => {
          setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000)
        })
      }
    }
  }
</script>

使用ES7 / ES2016的 async / await ,这将变得更简单:

<!-- MyComponent.vue -->
<template>
  <!-- 在一两秒后 myResolvedValue将变成"*Fancy* Resolved Value" -->
  <h2>Asynchronous Property {{ myResolvedValue }}</h2>
</template>

<script>
  function fancinessComesLater () {
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000)
    })
  }

  export default {
    asyncComputed: {
      async myResolvedValue() {
        return await fancinessComesLater()
      }
    }
  }
</script>

有关于vue-async-computed 更详细的使用和介绍,可以阅读其 官网 提供的相关介绍。

总结

今天主要学习了Vue中的计算属性。在Vue中的计算属性可以让我们很好的监听多个数据或者一个数据来维护返回一个状态值,只要其中一个或多个数据发生变化,则会重新计算整个函数体,重新皇家马德里回状态值,从而更新对应的视图(View)。其次,计算属性具有缓存,相比Vue中的方法而言,性能更佳。但Vue中的计算属性都是同步的,如果需要异步我们得依赖于vue-async-computed 。

由于自己是Vue的初学者,对Vue的计算属性也只是停留在表面层上的理解,如果从深层面上看,还是会存在一定问题。希望各咱大婶能指正或提供自己的经验。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Input 特殊事件onpopertychange和oninput
Jun 17 Javascript
jQuery AJAX实现调用页面后台方法和web服务定义的方法分享
Mar 01 Javascript
利用JS实现浏览器的title闪烁
Jul 08 Javascript
javascript实现十六进制颜色值(HEX)和RGB格式相互转换
Jun 20 Javascript
js表头排序实现方法
Jan 16 Javascript
js无法获取到html标签的属性的解决方法
Jul 26 Javascript
js异步编程小技巧详解
Aug 14 Javascript
JS字符串去除连续或全部重复字符的实例
Mar 08 Javascript
Vue实现搜索 和新闻列表功能简单范例
Mar 16 Javascript
vue+element-ui集成随机验证码+用户名+密码的form表单验证功能
Aug 05 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
Aug 29 Javascript
flexible.js实现移动端rem适配方案
Apr 07 Javascript
angular4中关于表单的校验示例
Oct 16 #Javascript
原生JS实现小小的音乐播放器
Oct 16 #Javascript
jQuery实现简单的回到顶部totop功能示例
Oct 16 #jQuery
老生常谈JavaScript面向对象基础与this指向问题
Oct 16 #Javascript
echarts饼图扇区添加点击事件的实例
Oct 16 #Javascript
Django中使用jquery的ajax进行数据交互的实例代码
Oct 15 #jQuery
JS继承与闭包及JS实现继承的三种方式
Oct 15 #Javascript
You might like
php传值赋值和传地址赋值用法实例分析
2015/06/20 PHP
解决windows上php xdebug 无法调试的问题
2020/02/19 PHP
HTML DOM的nodeType值介绍
2011/03/31 Javascript
基于jquery的多功能软键盘插件
2012/07/25 Javascript
javascript:void(0)使用探讨
2013/08/27 Javascript
JavaScript作用域与作用域链深入解析
2013/12/06 Javascript
jquery选择器之内容过滤选择器详解
2014/01/27 Javascript
Javascript+CSS实现影像卷帘效果思路及代码
2014/10/20 Javascript
DOM基础教程之使用DOM + Css
2015/01/20 Javascript
如何使用jquery修改css中带有!important的样式属性
2016/04/28 Javascript
D3.js实现雷达图的方法详解
2016/09/22 Javascript
安装Node.js并启动本地服务的操作教程
2018/05/12 Javascript
解决Mac node版本升级失败的问题
2018/05/16 Javascript
jQuery.extend 与 jQuery.fn.extend的用法及区别实例分析
2018/07/25 jQuery
使用JavaScript破解web
2018/09/28 Javascript
vue中实现Monaco Editor自定义提示功能
2019/07/05 Javascript
node.js处理前端提交的GET请求
2019/08/30 Javascript
vue中uni-app 实现小程序登录注册功能
2019/10/12 Javascript
JS实现随机抽取三人
2019/11/06 Javascript
详解Vue.js 响应接口
2020/07/04 Javascript
vue-video-player 断点续播的实现
2021/02/01 Vue.js
[00:21]DOTA2亚洲邀请赛 Logo演绎
2015/02/07 DOTA
在服务器端实现无间断部署Python应用的教程
2015/04/16 Python
搞笑的程序猿:看看你是哪种Python程序员
2015/06/12 Python
python爬虫使用cookie登录详解
2017/12/27 Python
python 计算数据偏差和峰度的方法
2019/06/29 Python
python如何实现单链表的反转
2020/02/10 Python
PyQt5 文本输入框自动补全QLineEdit的实现示例
2020/05/13 Python
python语言的优势是什么
2020/06/17 Python
个人公开承诺书
2014/03/28 职场文书
优秀少先队工作者事迹材料
2014/05/13 职场文书
高校师德师风自我剖析材料
2014/09/29 职场文书
幼儿园小班教师随笔
2015/08/14 职场文书
教师节随笔
2015/08/15 职场文书
Python中Permission denied的解决方案
2021/04/02 Python
分析mysql中一条SQL查询语句是如何执行的
2021/06/21 MySQL