9.1 什么是计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue</title>
</head>
<body>
<div id="app">
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello'
}
});
</script>
</div>

</html>

image.png

这里的表达式包含3个操作,并不是很清晰,所以遇到复杂逻辑时应该使用Vue特带的计算属性computed来进行处理。

9.2 计算属性的用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue</title>
</head>
<body>
<div id="app">
<div id="example">
{{getMessage}}
</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello'
},
computed: { // 放在computed中最后也会放在vm上,不能和methods与data重名
getMessage() {
return this.message.split('').reverse().join('')
}
}
});
</script>
</div>

</html>

9.3 计算属性使用技巧

计算属性可以依赖其他计算属性
计算属性不仅可以依赖当前Vue 实例的数据,还可以依赖其他实例的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue</title>
</head>
<body>
<div id="app1"></div>
<div id="app2">
{{getMessage}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm= new Vue({
el: '#app1',
data: {
message: 'World'
}
});
var vm2 = new Vue({
el: '#app2',
data: {
message: 'Hello'
},
computed: {
getMessage() {
return `${this.message} ${vm.message}`
}
}
});
</script>
</div>
</html>

9.4 getter和setter

每一个计算属性都包含一个getter 和一个setter ,我们上面的两个示例都是计算属性的默认用法, 只是利用了getter 来读取。
在你需要时,也可以提供一个setter 函数, 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发setter 函数,执行一些自定义的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue</title>
</head>
<body>
<div id="app">
<input type="text" v-model="getMessage"> <--模拟修改--!>
{{getMessage}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm= new Vue({
el: '#app',
data: {
hi:'Hello',
message: 'World'
},
computed:{
getMessage:{ //get,set方法
// getter
get(){
return this.hi + ' ' + this.message
},
// setter
set(newValue){
console.log('====================================');
console.log(newValue);
console.log('====================================');
var names = newValue.split(' ');
this.hi = names[0];
this.message = names[names.length - 1];
}
}
}
});
</script>
</html>


绝大多数情况下,我们只会用默认的getter 方法来读取一个计算属性,在业务中很少用到setter,所以在声明一个计算属性时,可以直接使用默认的写法,不必将getter 和setter 都声明。

9.5 质疑什么不直接用methods

我们可以将同一函数定义为一个方法而不是一个计算属性,两种方式的最终结果确实是完全相同的。只是一个使用getMessage()取值,一个使用getMessage取值。
然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
这就意味着只要 hi还没有发生改变,多次访问 getMessage计算属性会立即返回之前的计算结果,而不必再次执行函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue</title>
</head>
<body>
<div id="app">
<div>{{getMessage}}</div>
<div> {{getMessage1()}}</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script>
var vm= new Vue({
el: '#app',
data: {
hi:'Hello',
message: 'World'
},
computed:{
getMessage(){ //get,set方法
return this.hi + ' ' + this.message
//而使用计算属性,只要title没变,页面渲染是不会重新进这里来计算的,而是使用了缓存。
}
},
methods:{
getMessage1(){
return this.hi + ' ' + this.message
//进这个方法,再次计算。不是刷新,而是只要页面渲染,就会进方法里重新计算。
}
}
});
</script>
</html>