|
我不確定這是否是普遍的用法,但我發現 reactive 非常適合用來建立類似 OO 的封裝。
reactive會把 refs 展平,所以可以這麼寫:
function useClient() {
const name = ref('Alice')
const greeting = computed(() => `Hello ${name.value}`)
function updateName(newName: string) {
name.value = newName
}
return reactive({
name,
greeting,
updateName
})
}
在 component 裏:
const client = useClient()
client.greeting // => 'Hello Alice'
client.updateName('Bob')
client.greeting // => 'Hello Bob'
現在client管理它自己的狀態,其暴露的接口可以直接用在模板裏。
我們也可以組合這些對象和保留嚮應性:
function useOrder(client: ReturnType<typeof useClient>) {
const createdBy = computed(() => `Created by ${client.name}`)
// 你也可以在這裏調用 client.updateName
return reactive({
createdBy
})
}
const client = useClient()
const order = useOrder(client)
order.createdBy // => 'Created by Alice'
client.updateName('Bob')
order.createdBy // => 'Created by Bob'
我覺得這是 vue 相對於其他庫特別的屬性,我只需要傳遞一個對象,而它擁有自己的狀態和方法。
在現實中,這些對象一般會基於後端數據,我們可以在後端數據的基礎上擴展狀態和方法。
async function useOrder(client: ReturnType<typeof useClient>) {
const orderData = reactive(await fetchOrderData())
const paid = ref(false)
async function pay() {
const res = await paymentAPI()
paid.value = res.success
}
return reactive({
...toRefs(orderData), // 所有 orderData 的屬性會被暴露
// 我們需要 toRefs 來保持嚮應性
paid,
pay
})
}
現在給定一個 order ,我們可以直接在模板裏綁定order.paid 和order.pay。
本帖在 reddit 上的版本: https://www.reddit.com/r/vuejs/comments/1owezu4/reactive_as_an_object_encapsulation/
|