用 reactive 來實現 oo 對象的封裝

mizuhashi · 2025-11-14 06:36:27 · 216 次点击

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

本帖在 reddit 上的版本: https://www.reddit.com/r/vuejs/comments/1owezu4/reactive_as_an_object_encapsulation/

举报· 216 次点击
登录 注册 站外分享
1 条回复  
XCFOX 小成 2025-11-14 07:11:29
我都是写 reactive + class 的。 class 简直是天然的 store ,状态和方法一目了然。 ```ts import { reactive } from 'vue' class ClientStore {   name = 'Alice'   get greeting() {     return `Hello ${this.name}`   }   updateName(newName: string) {     this.name = newName   } } export const client = reactive(new ClientStore()) ```
返回顶部