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 相关文章推荐
表单填写时用回车代替TAB的实现方法
Oct 09 Javascript
js 操作select相关方法函数
Dec 06 Javascript
javascript 树形导航菜单实例代码
Aug 13 Javascript
浅析document.ready和window.onload的区别讲解
Dec 18 Javascript
js不能获取隐藏的div的宽度只能先显示后获取
Sep 04 Javascript
JS触发服务器控件的单击事件(详解)
Aug 06 Javascript
玩转NODE.JS(四)-搭建简单的聊天室的代码
Nov 11 Javascript
BootStrap selectpicker后台动态绑定数据的方法
Jul 28 Javascript
在Vue中获取组件声明时的name属性方法
Sep 12 Javascript
layui table 获取分页 limit的方法
Sep 20 Javascript
vue-drawer-layout实现手势滑出菜单栏
Nov 19 Vue.js
微信小程序实现modal弹出框遮罩层组件(可带文本框)
Dec 20 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+SQL 注入攻击的技术实现以及预防办法
2010/12/29 PHP
php简单浏览目录内容的实现代码
2013/06/07 PHP
destoon实现资讯信息前面调用它所属分类的方法
2014/07/15 PHP
wamp服务器访问php非常缓慢的解决过程
2015/07/01 PHP
豆瓣网的jquery代码实例
2008/06/15 Javascript
在IE下获取object(ActiveX)的Param的代码
2009/09/15 Javascript
Js如何判断客户端是PC还是手持设备简单分析
2012/11/22 Javascript
jquery 绑定回车动作扑捉回车键触发的事件
2014/03/26 Javascript
JQuery插件jcarousellite的参数中文说明
2015/05/11 Javascript
jquery实现用户信息修改验证输入方法汇总
2015/07/18 Javascript
Javascript获取数组中的最大值和最小值的方法汇总
2016/01/01 Javascript
再次谈论Javascript中的this
2016/06/23 Javascript
详细探究ES6之Proxy代理
2016/07/22 Javascript
简单实现js浮动框
2016/12/13 Javascript
vue.js删除动态绑定的radio的指定项
2017/06/02 Javascript
angular中使用Socket.io实例代码
2017/06/03 Javascript
Node.js dgram模块实现UDP通信示例代码
2017/09/26 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
2018/01/26 Javascript
vue项目前端知识点整理【收藏】
2019/05/13 Javascript
微信小程序批量监听输入框对按钮样式进行控制的实现代码
2019/10/12 Javascript
Javascript中的this,bind和that使用实例
2019/12/05 Javascript
Python微信库:itchat的用法详解
2017/08/14 Python
对Python的zip函数妙用,旋转矩阵详解
2018/12/13 Python
pytz格式化北京时间多出6分钟问题的解决方法
2019/06/21 Python
python模拟菜刀反弹shell绕过限制【推荐】
2019/06/25 Python
python实时监控logstash日志代码
2020/04/27 Python
django models里数据表插入数据id自增操作
2020/07/15 Python
Python的信号库Blinker用法详解
2020/12/31 Python
Sunglasses Shop德国站:欧洲排名第一的太阳镜网站
2017/08/01 全球购物
个人实用简单的自我评价
2013/10/19 职场文书
应届大学生的推荐信
2013/11/20 职场文书
高三上学期学习自我评价
2014/04/23 职场文书
2015暑假实习报告范文
2015/07/13 职场文书
2016年国庆节假期旅游工作总结
2016/04/01 职场文书
Spring Boot两种全局配置和两种注解的操作方法
2021/06/29 Java/Android
详解jQuery的核心函数和事件处理
2022/02/18 jQuery