Vue 3 计算属性(Computed Properties)知识点详解与案例代码
在 Vue 3 中,计算属性(Computed Properties) 是用于基于响应式数据派生新数据的一种方式。计算属性具有以下特点:
- 缓存性:只有在依赖的响应式数据发生变化时,计算属性才会重新计算,否则会返回缓存的结果。
- 可读性:计算属性用于获取数据,而不是修改数据。
- 响应性:计算属性会自动追踪其依赖的响应式数据,并在依赖变化时自动更新。
一、计算属性的语法知识点
1. 基本语法
在 Vue 3 中,计算属性通常在 setup
函数中使用 computed
函数来定义。
import { ref, computed } from 'vue';export default {setup() {const count = ref(0);const doubleCount = computed(() => count.value * 2);return {count,doubleCount};}
};
2. 使用 computed
函数
computed
函数接受一个 getter 函数 作为参数,并返回一个 只读的响应式引用(Readonly Ref)。
const double = computed(() => count.value * 2);
3. 可写的计算属性
默认情况下,计算属性是只读的。如果需要可写的计算属性,可以传递一个包含 get
和 set
方法的对象。
const firstName = ref('John');
const lastName = ref('Doe');const fullName = computed({get: () => `${firstName.value} ${lastName.value}`,set: (value) => {const parts = value.split(' ');firstName.value = parts[0];lastName.value = parts[1];}
});
4. 依赖追踪
计算属性会自动追踪其内部使用的响应式数据,并在这些数据变化时重新计算。
const firstName = ref('John');
const lastName = ref('Doe');const fullName = computed(() => `${firstName.value} ${lastName.value}`);
当 firstName
或 lastName
变化时,fullName
会自动更新。
5. 懒计算
计算属性只有在首次访问时才会计算,并且只有在依赖变化时才会重新计算。这使得计算属性在需要复杂计算时非常高效。
二、案例代码
以下是一个完整的 Vue 3 单文件组件(Single File Component, SFC)示例,展示了计算属性的使用,包括基本计算属性、可写的计算属性以及依赖追踪。
<template><div><h1>Vue 3 计算属性示例</h1><!-- 基本计算属性 --><div><p>当前计数: {{ count }}</p><p>双倍计数: {{ doubleCount }}</p><button @click="increment">增加计数</button></div><!-- 可写的计算属性 --><div><p>全名: {{ fullName }}</p><input v-model="fullName" placeholder="输入全名" /><p>名字: {{ firstName }}</p><p>姓氏: {{ lastName }}</p></div><!-- 依赖追踪示例 --><div><p>名字: {{ firstName }}</p><p>姓氏: {{ lastName }}</p><p>全名: {{ fullName }}</p><input v-model="firstName" placeholder="输入名字" /><input v-model="lastName" placeholder="输入姓氏" /></div></div>
</template><script>
import { ref, computed } from 'vue';export default {name: 'ComputedPropertiesExample',setup() {// 基本计算属性const count = ref(0);const doubleCount = computed(() => count.value * 2);const increment = () => {count.value++;};// 可写的计算属性const firstName = ref('John');const lastName = ref('Doe');const fullName = computed({get: () => `${firstName.value} ${lastName.value}`,set: (value) => {const parts = value.split(' ');if (parts.length >= 2) {firstName.value = parts[0];lastName.value = parts[1];} else {firstName.value = value;lastName.value = '';}}});return {count,doubleCount,increment,firstName,lastName,fullName};}
};
</script><style scoped>
h1 {color: #42b983;
}div {margin-bottom: 20px;
}button {padding: 5px 10px;margin-top: 5px;
}input {padding: 5px;margin-top: 5px;
}
</style>
代码详解
-
导入
ref
和computed
import { ref, computed } from 'vue';
ref
用于创建响应式数据。computed
用于创建计算属性。
-
基本计算属性
const count = ref(0); const doubleCount = computed(() => count.value * 2);
count
是一个响应式的数据。doubleCount
是一个计算属性,其值始终是count
的两倍。
-
增加计数的函数
const increment = () => {count.value++; };
increment
函数用于增加count
的值。
-
可写的计算属性
const fullName = computed({get: () => `${firstName.value} ${lastName.value}`,set: (value) => {const parts = value.split(' ');if (parts.length >= 2) {firstName.value = parts[0];lastName.value = parts[1];} else {firstName.value = value;lastName.value = '';}} });
fullName
是一个可写的计算属性。- 当
fullName
被设置时,会自动更新firstName
和lastName
。 - 当
firstName
或lastName
变化时,fullName
也会自动更新。
-
模板部分
<template><div><!-- 基本计算属性 --><div><p>当前计数: {{ count }}</p><p>双倍计数: {{ doubleCount }}</p><button @click="increment">增加计数</button></div><!-- 可写的计算属性 --><div><p>全名: {{ fullName }}</p><input v-model="fullName" placeholder="输入全名" /><p>名字: {{ firstName }}</p><p>姓氏: {{ lastName }}</p></div><!-- 依赖追踪示例 --><div><p>名字: {{ firstName }}</p><p>姓氏: {{ lastName }}</p><p>全名: {{ fullName }}</p><input v-model="firstName" placeholder="输入名字" /><input v-model="lastName" placeholder="输入姓氏" /></div></div> </template>
- 基本计算属性:展示当前计数和双倍计数,并提供按钮增加计数。
- 可写的计算属性:通过
v-model
绑定fullName
,输入全名会自动更新firstName
和lastName
。 - 依赖追踪示例:展示
firstName
和lastName
,并通过输入框修改它们,fullName
会自动更新。
-
样式部分
<style scoped> h1 {color: #42b983; }div {margin-bottom: 20px; }button {padding: 5px 10px;margin-top: 5px; }input {padding: 5px;margin-top: 5px; } </style>
- 使用
scoped
属性确保样式仅作用于当前组件。 - 设置了一些基本的样式。
- 使用
三、运行效果
-
基本计算属性
- 页面加载时,
count
为0
,doubleCount
为0
。 - 点击“增加计数”按钮,
count
增加,doubleCount
自动更新为count
的两倍。
- 页面加载时,
-
可写的计算属性
- 输入框中输入新的全名,例如
Jane Smith
,firstName
会更新为Jane
,lastName
会更新为Smith
。 - 修改
firstName
或lastName
,fullName
会自动更新。
- 输入框中输入新的全名,例如
-
依赖追踪示例
- 修改
firstName
或lastName
,fullName
会自动更新。 - 修改
fullName
,firstName
和lastName
会根据输入自动调整。
- 修改
四、案例代码
<template><div class="computed-demo"><h2>Vue3 计算属性示例</h2><!-- 基础用法展示 --><div class="basic-example"><h3>1. 基础只读计算属性</h3><p>姓: <input v-model="firstName" /></p><p>名: <input v-model="lastName" /></p><p>全名: {{ fullName }}</p><p>全名长度: {{ fullNameLength }}</p></div><!-- 可写计算属性展示 --><div class="writable-example"><h3>2. 可写计算属性</h3><p>输入全名: <input v-model="fullNameWritable" /></p><p>拆分结果: {{ firstName }} {{ lastName }}</p></div><!-- 计算属性与方法对比 --><div class="comparison-example"><h3>3. 计算属性与方法对比</h3><p>计算属性 (缓存): {{ reversedMessage }} (访问次数: {{ computedAccessCount }})</p><p>方法 (无缓存): {{ reversedMessageMethod() }} (调用次数: {{ methodCallCount }})</p><button @click="incrementCount">点击增加计数</button><p>当前计数: {{ count }}</p></div></div>
</template><script setup>
import { ref, computed } from 'vue';// 1. 基础示例数据
const firstName = ref('张');
const lastName = ref('三');// 基础只读计算属性:计算全名
const fullName = computed(() => {// 当firstName或lastName变化时,会重新计算return `${firstName.value} ${lastName.value}`;
});// 计算属性可以依赖其他计算属性
const fullNameLength = computed(() => {// 依赖fullName计算属性return fullName.value.length;
});// 2. 可写计算属性示例
const fullNameWritable = computed({// getter:获取值时调用get() {return `${firstName.value} ${lastName.value}`;},// setter:设置值时调用set(newValue) {// 将输入的全名拆分为姓和名const [first, last] = newValue.split(' ');firstName.value = first || '';lastName.value = last || '';}
});// 3. 计算属性与方法对比示例
const count = ref(0);
const message = ref('Hello Vue3');
const computedAccessCount = ref(0);
const methodCallCount = ref(0);// 计算属性版本:反转消息
const reversedMessage = computed(() => {computedAccessCount.value++;return message.value.split('').reverse().join('');
});// 方法版本:反转消息
function reversedMessageMethod() {methodCallCount.value++;return message.value.split('').reverse().join('');
}// 增加计数的方法
function incrementCount() {count.value++;
}
</script><style scoped>
.computed-demo {max-width: 800px;margin: 0 auto;padding: 20px;
}div > div {margin-bottom: 30px;padding: 15px;border: 1px solid #e0e0e0;border-radius: 8px;
}input {padding: 6px 10px;margin-left: 10px;border: 1px solid #ccc;border-radius: 4px;
}button {padding: 8px 16px;background-color: #42b983;color: white;border: none;border-radius: 4px;cursor: pointer;margin-top: 10px;
}button:hover {background-color: #359e75;
}
</style>
4.1.代码解析
- 基础只读计算属性
fullName
依赖firstName
和lastName
两个响应式数据- 当输入框中的值变化时,
fullName
会自动更新 fullNameLength
依赖fullName
这个计算属性,形成计算属性链
- 可写计算属性
fullNameWritable
同时定义了get
和set
方法- 当读取时,会调用
get
方法拼接全名 - 当修改输入框的值时,会调用
set
方法拆分全名到firstName
和lastName
- 计算属性与方法对比
- 点击按钮只会改变
count
的值,不会影响message
- 计算属性
reversedMessage
因为依赖没有变化,不会重新计算,访问次数不变 - 方法
reversedMessageMethod
每次访问都会重新执行,调用次数会增加
- 点击按钮只会改变
五、总结
通过上述知识点和案例代码,可以看出 Vue 3 的计算属性在处理基于响应式数据的派生数据时非常强大且高效。计算属性不仅简化了代码逻辑,还提高了应用的性能和可维护性。在实际开发中,合理使用计算属性可以大大提升开发效率和代码质量。