Vue中的computed
属性称为计算属性。在这一节中,咱们学习Vue中的计算属性如何使用?记得在学习Vue的模板相关的知识的时候,知道在模板内可使用表达式,并且模板内的表达式是很是的便利,但这种遍历是有必定的限制的,它们其实是用于一些简单的运算。也就是说,若是在模板中放入太多的逻辑会让模板太重并且难以维护。我们先来看一个示例:html
<div id="app"> <h1>{{ message.split('').reverse().join('') }}</h1> </div>
在这个示例中,模板再也不简单和清晰。你必须看一段时间才能意识到,这里是想要显示变量message
的翻转字符串。当你想要在模板中屡次引用此处的翻转字符串时,就会更加难以处理。vue
这就是对于任何复杂逻辑,你都应当使用计算属性的缘由。接下来我们一块儿来学习Vue中的计算属性。git
计算属性可用于快速计算视图(View)中显示的属性。这些计算将被缓存,而且只在须要时更新。github
在Vue中有多种方法为视图设置值:vue-cli
除此以外,咱们还可使用计算属性根据数据模型中的值或一组值来计算显示值。express
计算属性容许咱们对指定的视图,复杂的值计算。这些值将绑定到依赖项值,只在须要时更新。npm
例如,咱们能够在数据模型中有一个results
数组:数组
1 data () { 2 return { 3 results: [ 4 { 5 name: 'English', 6 marks: 70 7 }, 8 { 9 name: 'Math', 10 marks: 80 11 }, 12 { 13 name: 'History', 14 marks: 90 15 } 16 ] 17 } 18 }
假设咱们想要查看全部主题的总数。咱们不能使用filters
或expressions
来完成这个任务。promise
filters
:用于简单的数据格式,在应用程序的多个位置都须要它expressions
:不容许使用流操做或其余复杂的逻辑。他们应该保持简单这个时候,计算属性就能够派上用场。咱们能够向模型中添加一个计算值,以下:缓存
1 computed: { 2 totalMarks: function () { 3 let total = 0 4 let me = this 5 for (let i = 0; i < me.results.length; i++) { 6 total += parseInt(me.results[i].marks) 7 } 8 return total 9 } 10 }
totalMarks
计算属笥使用数组resultes
的marks
计算出总值。它只是循环遍历值并返回子总数。
而后,咱们能够在视图中显示计算值:
1 <div id="app"> 2 <div v-for="subject in results"> 3 <input v-model="subject.marks"> 4 <span>Marks for {{ subject.name }}: {{ subject.marks }}</span> 5 </div> 6 <div> 7 Total marks are: {{ totalMarks }} 8 </div> 9 </div>
咱们可使用Vue中的method
计算出学科的总分,最终获得的总数结果是相同的。
在上例的基础上,咱们把computed
区块中的totalMarks
函数总体移到methods
中。同时在模板中将{{ totalMarks }}
替换成 {{ totalMarks() }}
。 你最终看到的结果是同样的,
虽然这两种方式输出的结果是相同的,可是性能将遭受毁灭性的打击。使用这种方法,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] } } }
你在输入框中输入一个fullName
,而后点击set
按钮,能够看到对应的效果。你如今再运行app.fullName="Airen liao"
时,计算属性的setter
会被调用,app.firstName
和app.lastName
也相应地会被更新。以下图所示:
虽然计算属性在大多数状况下更合适,但有时候也须要一个自定义的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 } } })
上面代码是命令式的和重复的。将它与计算属性的版本进行比较:
1 let app = new Vue({ 2 el: '#app', 3 data () { 4 return { 5 firstName: 'Foo', 6 lastName: 'Bar' 7 } 8 }, 9 computed: { 10 fullName: function () { 11 return this.firstName + ' ' + this.lastName 12 } 13 } 14 })
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
的计算属性。
1 <!-- MyComponent.vue --> 2 <template> 3 <!-- 在一两秒后 myResolvedValue将变成"*Fancy* Resolved Value" --> 4 <h2>Asynchronous Property {{ myResolvedValue }}</h2> 5 </template> 6 7 <script> 8 export default { 9 asyncComputed: { 10 myResolvedValue () { 11 return new Promise((resolve, reject) => { 12 setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000) 13 }) 14 } 15 } 16 } 17 </script>
使用ES7 / ES2016的async / await
,这将变得更简单:
1 <!-- MyComponent.vue --> 2 <template> 3 <!-- 在一两秒后 myResolvedValue将变成"*Fancy* Resolved Value" --> 4 <h2>Asynchronous Property {{ myResolvedValue }}</h2> 5 </template> 6 7 <script> 8 function fancinessComesLater () { 9 return new Promise((resolve, reject) => { 10 setTimeout(() => resolve('*Fancy* Resolved Value!'), 1000) 11 }) 12 } 13 14 export default { 15 asyncComputed: { 16 async myResolvedValue() { 17 return await fancinessComesLater() 18 } 19 } 20 } 21 </script>
有关于vue-async-computed
更详细的使用和介绍,能够阅读其官网提供的相关介绍。
今天主要学习了Vue中的计算属性。在Vue中的计算属性可让咱们很好的监听多个数据或者一个数据来维护返回一个状态值,只要其中一个或多个数据发生变化,则会从新计算整个函数体,从新皇家马德里回状态值,从而更新对应的视图(View)。其次,计算属性具备缓存,相比Vue中的方法而言,性能更佳。但Vue中的计算属性都是同步的,若是须要异步咱们得依赖于vue-async-computed
。
原文: https://www.w3cplus.com/vue/vue-computed-intro.html © w3cplus.com