# Vue3教程 - 6 计算属性

和 Vue2 不同,Vue2 中是选项式API,Vue3 中是组合式API。

例如我们现在有一个需求,输入 firstName 和 lastName,然后拼接出结果,得到 fullName。

那么可能编写代码如下:

<template>
  <div>
    firstName:<input type="text" v-model="firstName">
  </div>
  <div>
    lastName:<input type="text" v-model="lastName">
  </div>
  <div>
    fullName:{{ firstName }} {{ lastName }}
  </div>
  
</template>

<!-- setup -->
<script lang="ts" setup>
import { ref } from 'vue'

let firstName = ref("")
let lastName = ref("")

</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

效果如下:

# 6.1 只读计算属性

如果想要通过 firstName 和 lastName 经过某些处理后,得到一个结果,例如将首字母大写。有些操作可能通过差值表达式可以完成,但是将这些逻辑写在模板里,不是好的设计。这个时候,我们可以使用计算属性 computed

举个栗子:

<template>
  <div>
    firstName:<input type="text" v-model="firstName">
  </div>
  <div>
    lastName:<input type="text" v-model="lastName">
  </div>
  <div>
    fullName:{{ fullName }}
  </div>
  
</template>

<!-- setup -->
<script lang="ts" setup>
import { ref, computed } from 'vue'  // 1.引入 computed

let firstName = ref("")
let lastName = ref("")

// 2.使用计算属性
let fullName = computed(() => {
  // 截取字符串,然后拼接返回,得到的结果是firstName首字母大写
  return firstName.value.slice(0, 1).toUpperCase() + firstName.value.slice(1) + " " + lastName.value
})

</script>
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

在上面的代码中,computed() 是一个函数,参数也是一个函数,参数的返回的结果是计算属性的结果。

只要计算属性function 内部所用到的任何响应式数据发送了变化,就会立即重新计算这个计算属性的值;另外计算属性的求值结果会被缓存起来,即使如果有多个地方使用到同一个计算属性,如果计算属性方法中的所有数据都没有发生过变化,则不会重新对计算属性求值;

运行结果:

# 6.2 可写计算属性

上面实现的计算属性的值是无法直接修改的,如果要修改是通过修改构成计算属性的值来完成的。

我们还可以通过给计算属性添加 gettersetter 方法来实现通过直接计算属性的值修改其他属性的值。

举个栗子:

<template>
  <div>
    firstName:<input type="text" v-model="firstName">
  </div>
  <div>
    lastName:<input type="text" v-model="lastName">
  </div>
  <div>
    fullName:{{ fullName }} 
    <button @click="changeFullName">修改fullName</button>
  </div>
  
</template>

<!-- setup -->
<script lang="ts" setup>
import { ref, computed } from 'vue'  // 1.引入 computed

let firstName = ref("")
let lastName = ref("")

// 2.使用计算属性
let fullName = computed({
  get() {
    // 截取字符串,然后拼接返回,得到的结果是firstName首字母大写
    return firstName.value.slice(0, 1).toUpperCase() + firstName.value.slice(1) + " " + lastName.value
  },
  set(val) {
    // 将fullName分割为两个部分,分别赋值给firstName和lastName
    let [str1, str2] = val.split(" ")
    firstName.value = str1
    lastName.value = str2
  }
})

function changeFullName() {
  // 直接修改fullName的值,会调用计算属性的set方法
  fullName.value = "Niu bi"
}

</script>
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
41

上面的代码中,点击按钮,会调用 changeFullName() 函数,在函数中直接修改计算属性 fullName 的值,会修改计算属性的 set 方法,在方法中,将 fullName 通过空格分割为两部分,分别赋值给 firstNamelastName