← 回筆記列表
前端
Computed Properties
<script setup>
- Vue
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// a computed ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
</script>
<template>
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</template>
- 為什麼要用
computed而不是普通函式?- 自動追蹤依賴: 你不需要手動告訴 Vue「當
author.books變動時要重新計算」,Vue 自己會知道。 - 快取(Cache)機制: 只要
author.books沒有改變,不管畫面重新渲染多少次,publishedBooksMessage都會直接回傳上一次算好的舊結果,不會浪費效能重新計算。
- 自動追蹤依賴: 你不需要手動告訴 Vue「當
Computed Caching vs. Methods
既然寫成普通函式(Method)也可以在畫面上印出一樣的結果,為什麼還要多一個 computed(計算屬性)?
快取機制
補充:Angular的實現方法跟改革
- 在Angular當中舊版的機制是用zone.js來處理 -> 攔截所有非步事件(如
setTimeout、HTTP 請求、點擊事件),但會導致兩個問題:- 沒有精準追蹤:Zone.js 其實不知道到底是哪一個變數改了,只知道「有事情發生」,所以會進行髒檢查(Dirty Checking)。
- 效能負擔:當專案變大時,容易造成不必要的全局過濾與重新渲染。
- 新版的Angular引入Signals的概念
Writable Computed
計算屬性預設僅支援 getter 方法。如果您嘗試為計算屬性賦值,將會收到執行時間警告。可以透過同時提供 getter 和 setter 方法來建立一個:
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>
Getting the Previous Value
可以取得上一次計算後回傳的結果,並非一定是初始值
可以取得先前的值:
<script setup>
import { ref, computed } from 'vue'
const count = ref(2)
// This computed will return the value of count when it's less or equal to 3.
// When count is >=4, the last value that fulfilled our condition will be returned
// instead until count is less or equal to 3
const alwaysSmall = computed((previous) => {
if (count.value <= 3) {
return count.value
}
return previous
})
</script>
搭配可寫入值:
<script setup>
import { ref, computed } from 'vue'
const count = ref(2)
const alwaysSmall = computed({
get(previous) {
if (count.value <= 3) {
return count.value
}
return previous
},
set(newValue) {
count.value = newValue * 2
}
})
</script>