介绍
- 基本概念:
computed()
接收一个getter
函数或者一个包含getter
和setter
函数的对象作为参数,并返回一个基于原始响应式数据计算得到的新的响应式数据对象。- 计算属性的值会根据其依赖的响应式数据自动更新,当依赖的数据发生变化时,计算属性的值也会自动重新计算。
- 返回值:
- 返回一个计算属性的响应式引用对象,可以通过
.value
属性来访问计算属性的值。
- 返回一个计算属性的响应式引用对象,可以通过
- 特点:
- 自动更新:计算属性会根据其依赖的响应式数据自动更新,无需手动触发更新。
- 缓存结果:计算属性会缓存其计算结果,只有当依赖的数据发生变化时才会重新计算。
示例
创建一个只读的计算属性
<template>
<div>
<div>姓名:<input type="text" v-model="name"></div>
<div>年龄:<input type="number" v-model="age"></div>
<div>信息:{{ info }}</div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
let name = ref('张三')
let age = ref(18)
let info = computed(() => {
return `${name.value}-${age.value}`
})
// 报错:无法为“value”赋值,因为它是只读属性。
// info.value = name.value
</script>
在这个例子中,当name.value
、age.value
发生改变时,info
的值会自动重新计算。
计算属性 info
是只读的。
创建一个可写的计算属性
在 Vue 3 中,使用computed
创建的计算属性默认情况下是只读的,只有明确提供了set
方法时,它才是可写的。
示例:
<template>
<div>
<div>姓名:<input type="text" v-model="name"></div>
<div>年龄:<input type="number" v-model="age"></div>
<!-- 在input中修改info,只能触发计算属性info的setter函数。 -->
<!-- 计算属性info本身的值是没有改变的。 -->
<div>信息:<input type="text" v-model="info"></div>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
let name = ref('张三')
let age = ref(18)
let info = computed({
get: () => `${name.value}-${age.value}`,
set: newValue => {
// setVal 是用户写入的计算属性的值
// 如果需要处理 set 逻辑,可以在这里添加代码
}
})
</script>
这里创建了一个可写的计算属性 info
,它的 getter
函数根据name
和age
的值返回一个自我介绍,setter
函数则根据传入的值更新info
的值。
注意:操作<input type="text" v-model="info">
修改info
的值,实际上只是触发了计算属性info
的set
方法调用。计算属性info
本身的值是没有任何改变的。
在set
方法中直接修改计算属性本身是不正确的,会导致无限循环:
let info = computed({
get: () => `我是${name.value},今年${age.value} 岁`,
set: newValue=> {
// newValue是用户写入的计算属性的值
// 在计算属性的set方法中,直接修改计算属性本身
info.value = newValue
}
})
在计算属性的set
方法中,直接修改计算属性本身,不会触发数据的双向绑定:
浏览器控制台输出错误:
Uncaught RangeError: Maximum call stack size exceeded...
要实现双向绑定的效果,应该在 set
方法中修改计算属性所依赖的响应式数据源:
let info = computed({
get: () => `${name.value}-${age.value}`,
set: newValue => {
// newValue 是用户写入的计算属性的值
const [newName, newAge] = newValue.split('-')
name.value = newName
age.value = Number(newAge)
}
})
当修改info
的值时,set
方法则根据传入的值(newValue
)会正确地更新name
和age
,get
方法根据name
和age
的值自动更新info
的值,从而实现双向绑定的效果。