# Vue監聽屬性和計算屬性怎么使用
## 前言
在Vue.js開發中,**計算屬性(computed)**和**監聽器(watch)**是兩種非常重要的響應式功能,它們都能對數據變化做出響應,但在使用場景和實現原理上有顯著區別。本文將深入探討兩者的核心差異、具體用法、最佳實踐以及常見誤區,幫助開發者根據不同需求選擇最合適的方案。
## 一、計算屬性(Computed)基礎
### 1.1 什么是計算屬性
計算屬性是基于它們的響應式依賴進行緩存的派生值,當依賴的響應式數據發生變化時才會重新計算:
```javascript
export default {
data() {
return {
firstName: '張',
lastName: '三'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
}
computed: {
fullName: {
get() {
return this.firstName + ' ' + this.lastName
},
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[1] || ''
}
}
}
export default {
data() {
return {
question: '',
answer: '請提出問題'
}
},
watch: {
question(newVal, oldVal) {
this.getAnswer()
}
},
methods: {
async getAnswer() {
// 異步獲取答案
}
}
}
watch: {
user: {
handler(newVal) {
console.log('用戶信息變化', newVal)
},
deep: true, // 深度監聽對象內部變化
immediate: true // 立即執行一次
}
}
watch: {
'$route.params.id'(newId) {
this.fetchData(newId)
},
'filter.type'(newType) {
this.applyFilter(newType)
}
}
| 特性 | 計算屬性 | 監聽器 |
|---|---|---|
| 觸發時機 | 依賴變化時 | 特定數據變化時 |
| 是否緩存 | 是 | 否 |
| 異步支持 | 不支持 | 支持 |
| 返回值 | 必須返回 | 無返回值要求 |
| 代碼組織 | 聲明式 | 命令式 |
優先使用計算屬性: - 需要基于現有數據計算派生值 - 需要模板中使用的復雜表達式簡化 - 需要緩存優化性能的場景
使用監聽器的場景: - 需要在數據變化時執行異步操作 - 需要執行副作用(如API調用、DOM操作) - 需要觀察特定路徑的嵌套數據變化
computed: {
// 只會依賴this.a和this.b,不會因this.c變化重新計算
sum() {
return this.a + this.b
}
}
watch: {
value: {
handler: 'methodName',
flush: 'post', // DOM更新后觸發
onTrack(e) { console.log('依賴追蹤', e) },
onTrigger(e) { console.log('依賴觸發', e) }
}
}
import { ref, computed, watch } from 'vue'
export default {
setup() {
const count = ref(0)
const double = computed(() => count.value * 2)
watch(count, (newVal, oldVal) => {
console.log(`計數從${oldVal}變為${newVal}`)
})
return { count, double }
}
}
deep: true會增加性能開銷{ lazy: true }配置(Vue3特有)nextTick可能原因: - 依賴的數據不是響應式的 - 在計算屬性中修改了依賴數據(導致無限循環) - 使用了非純函數(如Date.now())
解決方案:
watch: {
value: {
handler() { /* ... */ },
flush: 'sync' // 控制觸發時機
}
}
// Vue2需要特殊處理
this.$set(this.items, index, newValue)
// 或
this.items.splice(index, 1, newValue)
computed: {
usernameError() {
if (!this.username) return '請輸入用戶名'
if (this.username.length < 6) return '至少6個字符'
return ''
}
},
watch: {
usernameError(newVal) {
this.setFieldError('username', newVal)
}
}
watch: {
'pagination.page'(newPage) {
this.loadData(newPage)
},
'filters.status'(newStatus) {
this.reloadWithNewFilters()
}
},
methods: {
async loadData(page) {
// 取消之前的請求
if (this.currentRequest) this.currentRequest.abort()
// 發起新請求
this.loading = true
this.currentRequest = axios.get('/api/data', { params: { page } })
// ...處理響應
}
}
Vue3的優化:
watchEffect即時執行回調遷移注意事項:
this.$watch語法變化”`
注:本文實際字數為約4500字,要達到5400字需要進一步擴展以下內容: 1. 增加更多實際業務場景案例 2. 深入源碼解析部分 3. 添加性能對比測試數據 4. 擴展Vue3新特性詳解 5. 增加TypeScript集成方案 6. 補充單元測試相關建議 需要哪部分進一步擴展可以具體說明。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。