Skip to content
On this page

计算属性(computed)

什么是计算属性

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

html
<!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>
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

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

计算属性的用法

html
<!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>
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

计算属性使用技巧

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

html
<!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>
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

getter和setter

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

html
<!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>
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

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

质疑什么不直接用methods

通过上面的代码,可以看到使用计算属性,让界面变得更加的简洁。

使用计算属性还有一个好处:

其实细心的话就会发现,调用methods里的方法也能实现和计算属性一样的效果,既然使用methods就可以实现,那为什么还需要计算属性呢?原因就是计算属性是基于他的依赖缓存的(所依赖的还是data中的数据)。一个计算属性所依赖的数据发生变化时,他才会重新取值

也就是说:只要相关依赖没有改变,对此访问计算属性得到的是之前缓 存的结果,不会多次执行。

下面我们测试一下:

html
 <p>
    <!-- 总人数:{{users.length+"个"}} -->
    总人数:{{total}} 总人数:{{total}}
  </p>
1
2
3
4

在上面的代码中,我们使用total了两次。

下面在看一下关于计算属性中的代码修改:

javascript
 computed: {
    total() {
      console.log("aaa");
      // 计算属性是有缓存性:如果值没有发生变化,则页面不会重新渲染
      return this.users.length + "";
    },
  },
1
2
3
4
5
6
7

这里,我们通过console输出字符串aaa,但是在控制台上只是输出了一次,因为,第二次使用total的时候,发现值没有变化,所以直接从缓存中获取了对应的值。并没有重新进行计算,这样带来的好处就是,性能得到了提升。

下面,我们换成methods函数的形式来看一下:

html
<p>
  <!-- 总人数:{{users.length+"个"}} -->
  总人数:{{total}} 总人数:{{total}} 总人数:{{getTotal()}}
  总人数:{{getTotal()}}
</p>
1
2
3
4
5

在上面的代码中,调用了两次getTotal方法。

getTotal方法的实现如下:

javascript
  methods: {
    getTotal: function () {
      console.log("methods");
      return this.users.length + "";
    },
  },
1
2
3
4
5
6

实现的方式是差不多的,但是这里却执行了两次。(注意:由于本案例中给每一个li标签添加了*@mousemove*,所以只要鼠标移动到列表上,就会导致页面重新渲染,这时会不断的调用getTotal方法。)

所以通过上面案例的演示,可以明确的看出计算属性是有缓存的,也就是所依赖的data属性中的数据没有变化,那么是不会重新计算的。所以提升了对应的性能。

所以说,在进行大量耗时计算的时候,建议使用计算属性来完成。

如下代码:

javascript
 data: {
   selectItem: "",
   num: 100
  }
1
2
3
4

在data中定义了num 属性,并且初始值为100、

下面在计算属性中进行求和的运算,代码实现如下:

javascript
 computed: {
    total() {
      console.log("aaa");
      // 计算属性是有缓存性:如果值没有发生变化,则页面不会重新渲染
      // return this.users.length + "个";
      let count = 0;
      for (let i = 0; i <= this.num; i++) {
        count += i;
      }
      return count;
    },
  },
1
2
3
4
5
6
7
8
9
10
11
12

通过演示,可以发现计算属性只是在第一次调用的时候,执行了一次,后续由于所依赖的数据num没有发生变化,所以即时调用多次,也并没有重新进行计算,而是获取上次计算的结果,所以说在进行大量耗时计算的时候,通过计算属性可以提升性能。

沪ICP备20006251号-1