在 Vue 开发中,我们经常需要根据已有数据处理并返回新的结果,比如对列表进行过滤、拼接字符串、计算数值总和等。此时,computed计算属性和methods方法都能实现这个需求,但很多初学者会疑惑:两者到底有什么区别?什么时候该用 computed,什么时候该用 methods?
这篇文章将从computed的缓存机制入手,深入剖析它与methods的核心差异,帮你彻底搞懂二者的使用场景。
一、先看一个简单的例子
我们先通过一个基础案例,直观感受下computed和methods的表现差异。
假设我们有一个 Vue 实例,里面有firstName和lastName两个数据,需要拼接成完整的姓名:
1. 使用 methods 实现
<template>
<div>
<p>姓名:{{ getFullName() }}</p>
<p>姓名:{{ getFullName() }}</p>
<p>姓名:{{ getFullName() }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '张',
lastName: '三'
}
},
methods: {
getFullName() {
console.log('methods执行了');
return this.firstName + this.lastName;
}
}
}
</script>
此时打开控制台,会发现methods执行了被打印了三次—— 因为模板中每次调用getFullName(),方法都会重新执行一次。
2. 使用 computed 计算属性实现
<template>
<div>
<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '张',
lastName: '三'
}
},
computed: {
fullName() {
console.log('computed执行了');
return this.firstName + this.lastName;
}
}
}
</script>
这时候控制台只打印了一次computed执行了—— 即使模板中多次引用fullName,计算属性也只执行了一次。
这个差异的根源,就是computed的缓存机制。
二、computed 的缓存机制:到底是什么?
Vue 的计算属性基于其依赖的响应式数据进行缓存。简单来说:
计算属性会记住它的依赖(比如上面例子中的
firstName和lastName),只有当依赖的响应式数据发生变化时,计算属性才会重新计算并更新结果;如果依赖没有变化,每次访问计算属性都会直接返回缓存的结果,不会重新执行函数。
缓存机制的底层逻辑(简易版)
- 当 Vue 实例初始化时,会解析计算属性的函数,收集其中依赖的响应式数据(如
firstName、lastName)。 - 第一次访问计算属性时,执行函数并将结果缓存起来。
- 当依赖的响应式数据发生变化时,Vue 会触发依赖更新,清空计算属性的缓存,下次访问时重新计算并缓存新结果。
- 如果依赖没有变化,直接返回缓存的结果。
举个例子:依赖变化时的缓存更新
我们给上面的例子加一个按钮,修改firstName:
<template>
<div>
<p>姓名:{{ fullName }}</p>
<p>姓名:{{ fullName }}</p>
<button @click="changeFirstName">修改姓</button>
</div>
</template>
<script>
export default {
data() {
return {
firstName: '张',
lastName: '三'
}
},
computed: {
fullName() {
console.log('computed执行了');
return this.firstName + this.lastName;
}
},
methods: {
changeFirstName() {
this.firstName = '李';
}
}
}
</script>
此时:
- 页面初始化:打印 1 次
computed执行了(缓存结果:张三)。 - 点击按钮修改
firstName为 “李”:依赖变化,打印 1 次computed执行了(重新计算并缓存:李四)。 - 再次访问
fullName:直接返回缓存的 “李四”,不再执行函数。
三、computed vs methods:核心区别
通过上面的例子,我们可以总结出二者的核心差异:
| 特性 | computed 计算属性 | methods 方法 |
|---|---|---|
| 缓存机制 | 基于依赖的响应式数据缓存结果 | 无缓存,每次调用都会重新执行函数 |
| 调用方式 | 模板中直接引用(如{{ fullName }}),无需加括号 | 模板中需要加括号调用(如{{ getFullName() }}) |
| 返回值要求 | 必须有返回值(因为要缓存结果) | 可以有返回值,也可以无返回值(如处理事件) |
| 响应式依赖 | 自动追踪依赖的响应式数据 | 不会自动追踪,仅在调用时执行 |
| 适用场景 | 数据处理、数据派生(依赖固定数据) | 事件处理、一次性操作、复杂逻辑(无需缓存) |
补充:computed 的 setter 和 getter
计算属性默认只有 getter(取值函数),但也可以设置 setter(赋值函数),实现 “可写的计算属性”:
computed: {
fullName: {
// getter:取值时执行
get() {
return this.firstName + this.lastName;
},
// setter:赋值时执行
set(newValue) {
const [first, last] = newValue.split(' ');
this.firstName = first;
this.lastName = last;
}
}
}
此时,我们可以直接给fullName赋值:this.fullName = '王 五',setter 会被触发,自动更新firstName和lastName。而 methods 无法实现这种 “赋值联动” 的效果。
四、什么时候用 computed?什么时候用 methods?
结合缓存机制和使用场景,我们可以给出明确的选择原则:
优先用 computed 的场景
- 需要根据已有响应式数据派生新数据:比如拼接字符串、过滤列表(
filteredList)、计算数值(totalPrice)等。 - 数据会被多次访问:比如模板中多次引用、多个地方使用同一个派生数据,缓存能减少重复计算,提升性能。
- 依赖的数据源是固定的响应式数据:计算属性的缓存只有在依赖变化时才会更新,适合这种场景。
优先用 methods 的场景
- 处理事件逻辑:比如按钮点击、表单提交等(这是 methods 最常见的用途)。
- 执行一次性操作:比如请求接口、操作 DOM、随机数生成(因为随机数不是响应式依赖,computed 无法缓存)。
- 复杂逻辑且无需缓存:比如需要传递参数的函数(computed 无法直接接收参数,虽然可以通过闭包实现,但不如 methods 直观)。
- 不依赖响应式数据的操作:比如纯逻辑计算,没有依赖的响应式数据,computed 的缓存机制就失去了意义。
注意:computed 不能直接接收参数?
有同学会问:computed 能不能像 methods 一样接收参数?
答案是:默认不能,但可以通过返回函数的方式间接实现,比如:
computed: {
getFullName() {
// 返回一个函数,接收参数
return (middleName) => {
return this.firstName + middleName + this.lastName;
}
}
}
模板中调用:{{ getFullName('小') }}。
但这种方式会失去缓存机制—— 因为每次调用都会返回一个新的函数,相当于每次执行都是新的计算,此时 computed 的缓存优势就没了。所以如果需要传递参数,优先用 methods。
五、性能影响:缓存的重要性
在简单场景下,computed 和 methods 的性能差异并不明显,但在复杂计算或大量数据处理的场景下,缓存机制的影响会被放大。
比如,我们有一个包含 1000 条数据的列表,需要过滤出符合条件的项:
// 用computed:只在列表或过滤条件变化时重新计算
computed: {
filteredList() {
return this.list.filter(item => item.age > 18);
}
}
// 用methods:每次调用都要遍历1000条数据
methods: {
getFilteredList() {
return this.list.filter(item => item.age > 18);
}
}
如果模板中多次引用这个过滤后的列表,computed 只需要执行一次过滤,而 methods 需要执行多次,性能差异会非常明显。
六、总结
- 缓存是 computed 和 methods 的核心区别:computed 基于响应式依赖缓存结果,methods 无缓存。
- 调用方式不同:computed 在模板中直接引用,methods 需要加括号调用。
- 使用场景不同:
- computed:适合数据派生、多次访问的场景,利用缓存提升性能。
- methods:适合事件处理、一次性操作、需要传参的场景。
- 不要为了用 computed 而用 computed,如果不需要缓存,methods 反而更简单。
理解了 computed 的缓存机制和二者的区别,你就能在 Vue 开发中做出更合理的选择,写出性能更优、更易维护的代码。


被折叠的 条评论
为什么被折叠?



