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. **计算属性能接收参数吗?**
|
|||
|
- 不能直接接收参数,如需参数化应使用方法
|
|||
|
- 替代方案:返回函数或使用闭包
|