## [计算属性](https://cn.vuejs.org/v2/guide/computed.html#计算属性 "计算属性")
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
~~~
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
~~~
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 `message` 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。
所以,对于任何复杂逻辑,你都应当使用**计算属性**。
### [基础例子](https://cn.vuejs.org/v2/guide/computed.html#基础例子 "基础例子")
~~~
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
~~~
~~~
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
~~~
结果:
Original message: "Hello"
Computed reversed message: "olleH"
这里我们声明了一个计算属性 `reversedMessage`。我们提供的函数将用作属性 `vm.reversedMessage` 的 getter 函数:
~~~
console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'
~~~
你可以打开浏览器的控制台,自行修改例子中的 vm。`vm.reversedMessage` 的值始终取决于 `vm.message` 的值。
你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 `vm.reversedMessage` 依赖于 `vm.message`,因此当 `vm.message` 发生改变时,所有依赖 `vm.reversedMessage` 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。
### [计算属性缓存 vs 方法](https://cn.vuejs.org/v2/guide/computed.html#计算属性缓存-vs-方法 "计算属性缓存 vs 方法")
你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:
~~~
<p>Reversed message: "{{ reversedMessage() }}"</p>
~~~
~~~
// 在组件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
~~~
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是**计算属性是基于它们的响应式依赖进行缓存的**。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 `message` 还没有发生改变,多次访问 `reversedMessage` 计算属性会立即返回之前的计算结果,而不必再次执行函数。
这也同样意味着下面的计算属性将不再更新,因为 `Date.now()` 不是响应式依赖:
~~~
computed: {
now: function () {
return Date.now()
}
}
~~~
相比之下,每当触发重新渲染时,调用方法将**总会**再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 **A**,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 **A** 。如果没有缓存,我们将不可避免的多次执行 **A** 的 getter!如果你不希望有缓存,请用方法来替代。
### [计算属性 vs 侦听属性](https://cn.vuejs.org/v2/guide/computed.html#计算属性-vs-侦听属性 "计算属性 vs 侦听属性")
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:**侦听属性**。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 `watch`——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 `watch` 回调。细想一下这个例子:
~~~
<div id="demo">{{ fullName }}</div>
~~~
~~~
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
~~~
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
~~~
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
~~~
### [计算属性的 setter](https://cn.vuejs.org/v2/guide/computed.html#计算属性的-setter "计算属性的 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]
}
}
}
// ...
~~~
现在再运行 `vm.fullName = 'John Doe'` 时,setter 会被调用,`vm.firstName` 和 `vm.lastName` 也会相应地被更新。
- 我们在做什么?
- 为什么是内存?
- 我们实际上在做什么
- HTML基础
- Web原理和HTML简介
- Web原理
- HTML概念
- HTML标签
- 标签
- HTML固定基本结构
- 第一个HTML页面
- 工具的使用
- 标题
- <hr>和<p>标签
- 路径概念
- 超级链接
- 列表
- 表格
- 表单的设计与使用
- 表单域的原理
- 文本框和密码框
- 单选框和复选框
- 下拉列表框
- 多行文本和上传
- 提交按钮和重置按钮
- 为CODING COFFEE加入在线购买页
- HTML5
- 定位服务
- CSS
- CSS的基础使用
- CSS简介
- CSS样式规则和加载方式
- 选择器
- 伪类
- CSS优先级和层叠
- CSS颜色
- 背景图片
- 文本
- CSS列表
- DIV+CSS布局
- 内联元素和区块元素介绍
- Display属性
- 盒子模型的边距和边框
- 浮动和清除浮动
- 用Position属性进行定位
- 专题:居中和对齐
- flex布局
- CSS新特性
- CSS3边框
- 动画
- Javascript
- HelloWorld
- 语句与变量
- 一切皆对象
- 标识符、注释和区块
- 基本数据类型和引用数据类型
- 语句
- 条件语句
- 循环语句
- 标准库
- Array对象
- Number对象
- String对象
- JSON对象
- Math对象
- Date对象
- 数据类型
- typeof运算符
- number
- 字符串
- 布尔类型
- 函数
- 数组
- Dom模型
- Dom和Dom节点
- 特征相关属性
- 节点对象方法
- Element对象
- Attribute对象
- Text节点和CSS操作
- 事件模型
- WebStorage
- BOM模型
- window对象
- 计时事件
- jQuery基础
- 认识jQuery
- jQuery对象和DOM对象
- jQuery选择器
- jQuery Dom操作
- 查找节点和创建节点
- 插入节点和删除节点
- 复制节点和替换节点
- 包裹节点和属性操作
- 样式操作
- 设置和获取HTML、文本和值
- 遍历节点和CSS操作
- jQuery 事件和动画
- 事件绑定与冒泡处理
- jQuery动画
- jQuery 插件
- validate 插件
- jQuery与Ajax的应用
- Ajax简介
- jquery中的Ajax
- Vue.js基础与实战
- HelloWorld
- v-for、v-on、v-model
- 组件化编程
- 生命周期函数(钩子)
- 计算属性、侦听器、方法
- class与style绑定
- 关于组件的一些问题
- 单项数据流和Prop验证
- 项目环境搭建
- 关于git的一些情况
- JavaWeb教程
- 对象和类的概念
- 对象和类的介绍
- 对象和类的介绍2
- 类的继承与权限控制
- Object类
- 多态的内容
- 容器
- 流
- Servlet
- Servlet练习
- Session和Cookie
- JSP
- 内置对象
- JSTL和EL
- JDBC
- 文件上传和下载
- 过滤器
- 数据库
- 数据库介绍
- MySQL的安装
- SQL
- 表基本操作
- 修改数据语句
- 数据检索操作
- 多表数据操作
- 表结构设计
- 综合应用
- 作业与练习
- Maven教程
- Maven安装配置