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 相关文章推荐
封装了一个js图片轮换效果的函数
Sep 28 Javascript
javascript中的循环语句for语句深入理解
Apr 04 Javascript
常用的JavaScript模板引擎介绍
Feb 28 Javascript
详解js中构造流程图的核心技术JsPlumb(2)
Dec 08 Javascript
javascript移动开发中touch触摸事件详解
Mar 18 Javascript
Vue.js中轻松解决v-for执行出错的三个方案
Jun 09 Javascript
Bootstrap Table 删除和批量删除
Sep 22 Javascript
AngularJS 控制器 controller的详解
Oct 17 Javascript
详解vue-meta如何让你更优雅的管理头部标签
Jan 18 Javascript
Vue项目中设置背景图片方法
Feb 21 Javascript
jQuery轻量级表单模型验证插件
Oct 15 jQuery
js实现轮播图效果 z-index实现轮播图
Jan 17 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开启opcache提升代码性能
2015/04/26 PHP
Yii2中使用join、joinwith多表关联查询
2016/06/30 PHP
基于jquery的loading 加载提示效果实现代码
2011/09/01 Javascript
JS定时器实例
2013/04/17 Javascript
JavaScript+html5 canvas制作的百花齐放效果完整实例
2016/01/26 Javascript
JS在浏览器中解析Base64编码图像
2017/02/09 Javascript
jQuery选择器_动力节点Java学院整理
2017/07/05 jQuery
JS非行间样式获取函数的实例代码
2018/06/05 Javascript
JavaScript对象拷贝与Object.assign用法实例分析
2018/06/20 Javascript
jQuery实现轮播图及其原理详解
2020/04/12 jQuery
微信小程序视图控件与bindtap之间的问题的解决
2019/04/08 Javascript
微信小程序全局变量GLOBALDATA的定义和调用过程解析
2019/09/23 Javascript
JavaScript实现左右滚动电影画布
2020/02/06 Javascript
[40:55]Liquid vs LGD 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
Python的Tornado框架异步编程入门实例
2015/04/24 Python
Python psutil模块简单使用实例
2015/04/28 Python
在Python中操作字符串之replace()方法的使用
2015/05/19 Python
Python找出9个连续的空闲端口
2016/02/01 Python
python+pandas分析nginx日志的实例
2018/04/28 Python
Sanic框架配置操作分析
2018/07/17 Python
python打开windows应用程序的实例
2019/06/28 Python
django的ORM操作 增加和查询
2019/07/26 Python
Python控制台输出时刷新当前行内容而不是输出新行的实现
2020/02/21 Python
PyTorch实现重写/改写Dataset并载入Dataloader
2020/07/14 Python
matplotlib绘制多子图共享鼠标光标的方法示例
2021/01/08 Python
HTML5 script元素async、defer异步加载使用介绍
2013/08/23 HTML / CSS
html5移动端自适应布局的实现
2020/04/15 HTML / CSS
社会学专业求职信
2014/07/17 职场文书
夫妻双方自愿离婚协议书怎么写
2014/12/01 职场文书
总经理助理岗位职责范本
2015/03/31 职场文书
施工员岗位职责范本
2015/04/11 职场文书
六一文艺汇演主持词
2015/06/30 职场文书
幼儿园班级管理心得体会
2016/01/07 职场文书
详解分布式系统中如何用python实现Paxos
2021/05/18 Python
为什么代码规范要求SQL语句不要过多的join
2021/06/23 MySQL
Python 第三方库 openpyxl 的安装过程
2022/12/24 Python