V2EX 前天 10:53
Vue 的 reactive 如何实现面向对象式的封装
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文探讨了如何在 Vue.js 中利用 `reactive` 函数实现类似面向对象编程(OOP)的封装。作者展示了如何通过 `reactive` 将 `ref` 展平,创建可组合的逻辑单元,例如 `useClient` 和 `useOrder`。这种方式使得状态和方法能够被封装在一个对象中,可以直接在组件模板中使用,简化了状态管理和代码组织。文章还进一步演示了如何通过 `reactive` 结合 `toRefs` 和异步操作来管理更复杂的状态,如从后端获取数据并添加行为,从而在模板中直接调用支付方法等,强调了 Vue 在这一方面的独特性。

💡 **Vue `reactive` 实现 OOP 式封装**:文章指出,Vue 的 `reactive` 函数非常适合用于构建类似面向对象编程(OOP)的封装。通过 `reactive`,可以方便地将响应式状态(如 `ref`)和相关方法聚合到一个对象中,形成一个独立的逻辑单元,便于管理和复用。

🧩 **可组合的逻辑单元**:作者通过 `useClient` 和 `useOrder` 的例子,展示了如何创建可组合的逻辑单元。`useClient` 封装了客户端的名称和问候语,`useOrder` 则可以依赖 `useClient` 的状态。这种组合方式允许将复杂的功能拆解成更小、更易于管理的块,提高了代码的可维护性。

📦 **组件模板的直接集成**:通过 `reactive` 封装的逻辑单元,可以直接暴露其状态和方法给组件使用。例如,`client.greeting` 和 `client.updateName` 可以直接在模板中访问和调用,无需额外的 props 传递或状态提升,极大地简化了组件与逻辑单元的交互。

🌐 **处理异步数据与行为**:文章还演示了如何使用 `reactive` 结合 `toRefs` 来处理异步获取的数据,并为其添加行为。例如,`useOrder` 函数可以从后端获取订单数据,并通过 `reactive` 暴露数据属性(使用 `toRefs` 保持响应性)以及 `pay` 方法,使得这些异步管理的状态和行为也能在模板中无缝使用。

✨ **Vue 的独特性**:作者认为,这种将状态、方法以及异步逻辑封装在一个对象中,并能直接在模板中使用的能力,是 Vue 相较于其他库的独特优势,它提供了一种更加直观和灵活的状态管理模式。

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

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Vue.js reactive Composition API 面向对象 封装 状态管理 代码组织 Vue.js reactive Composition API Object-Oriented Encapsulation State Management Code Organization
相关文章