我不確定這是否是普遍的用法,但我發現 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/
