166 lines
3.8 KiB
Markdown
166 lines
3.8 KiB
Markdown
# Vue2 计算属性详解文档
|
||
|
||
## 一、基本概念
|
||
|
||
计算属性(Computed Properties)是 Vue2 中用于声明式地定义派生数据的特性。它们基于响应式依赖进行缓存,只在相关依赖发生改变时才重新计算。
|
||
|
||
## 二、代码示例解析
|
||
|
||
```html
|
||
<div id="app">
|
||
姓:<input type="text" v-model="firstName">
|
||
名:<input type="text" v-model="lastName">
|
||
全名:<span>{{fullName}}</span>
|
||
</div>
|
||
|
||
<script>
|
||
const vm = new Vue({
|
||
el: "#app",
|
||
data() {
|
||
return {
|
||
firstName: "",
|
||
lastName: ""
|
||
}
|
||
},
|
||
computed: {
|
||
fullName: {
|
||
get() {
|
||
return `${this.firstName}-${this.lastName}`
|
||
},
|
||
set(val) {
|
||
// 可选的setter
|
||
}
|
||
}
|
||
}
|
||
})
|
||
</script>
|
||
```
|
||
|
||
## 三、核心特性
|
||
|
||
### 1. 计算属性 vs 方法
|
||
|
||
| 特性 | 计算属性 | 方法 |
|
||
| -------- | -------------------------- | --------------------------- |
|
||
| 缓存 | 有缓存,依赖不变不重新计算 | 每次调用都执行 |
|
||
| 调用方式 | 作为属性访问 | 需要调用执行 |
|
||
| 适用场景 | 派生数据 | 事件处理/需要重复执行的逻辑 |
|
||
|
||
### 2. 完整语法结构
|
||
|
||
```javascript
|
||
computed: {
|
||
属性名: {
|
||
get() {
|
||
// 计算逻辑
|
||
return 派生值
|
||
},
|
||
set(value) {
|
||
// 可选的反向更新逻辑
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 简写形式(只读场景)
|
||
|
||
```javascript
|
||
computed: {
|
||
fullName() {
|
||
return `${this.firstName}-${this.lastName}`
|
||
}
|
||
}
|
||
```
|
||
|
||
## 四、最佳实践
|
||
|
||
1. **命名规范**:
|
||
- 使用名词形式(如 `fullName`)
|
||
- 避免动词开头(这是方法的命名习惯)
|
||
|
||
2. **纯计算逻辑**:
|
||
- 不要在getter中执行异步操作或副作用
|
||
- 复杂计算考虑拆分为多个计算属性
|
||
|
||
3. **setter使用场景**:
|
||
- 当需要反向更新依赖数据时
|
||
- 示例:
|
||
```javascript
|
||
set(val) {
|
||
const parts = val.split('-');
|
||
this.firstName = parts[0] || '';
|
||
this.lastName = parts[1] || '';
|
||
}
|
||
```
|
||
|
||
## 五、高级用法
|
||
|
||
### 1. 依赖多个数据源
|
||
|
||
```javascript
|
||
computed: {
|
||
summary() {
|
||
return `总计:${this.items.length}件,${this.totalPrice}元`
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 结合过滤器使用
|
||
|
||
```javascript
|
||
computed: {
|
||
formattedDate() {
|
||
return dayjs(this.rawDate).format('YYYY-MM-DD')
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. 计算属性嵌套
|
||
|
||
```javascript
|
||
computed: {
|
||
baseInfo() {
|
||
return { ...this.user, age: this.calcAge }
|
||
},
|
||
calcAge() {
|
||
return new Date().getFullYear() - this.user.birthYear
|
||
}
|
||
}
|
||
```
|
||
|
||
## 六、性能优化
|
||
|
||
1. **减少大数组计算**:
|
||
```javascript
|
||
computed: {
|
||
visibleItems() {
|
||
return this.items.filter(item =>
|
||
item.name.includes(this.search) &&
|
||
item.status === 'active'
|
||
)
|
||
}
|
||
}
|
||
```
|
||
|
||
2. **避免频繁计算**:
|
||
- 对于复杂计算考虑使用 `methods` + 防抖
|
||
- 或使用 `watch` 手动控制计算时机
|
||
|
||
3. **缓存利用**:
|
||
- 相同依赖多次访问不会重复计算
|
||
- 模板中可安全多次引用同一计算属性
|
||
|
||
## 七、常见问题
|
||
|
||
1. **为什么计算属性不更新?**
|
||
- 检查依赖数据是否是响应式的
|
||
- 确保没有在getter中意外修改了依赖数据
|
||
|
||
2. **何时使用计算属性 vs watch?**
|
||
- 计算属性:基于多个数据的派生数据
|
||
- watch:需要在数据变化时执行异步或开销较大的操作
|
||
|
||
3. **计算属性能接收参数吗?**
|
||
- 不能直接接收参数,如需参数化应使用方法
|
||
- 替代方案:返回函数或使用闭包
|