
我不定是否是普遍的用法,但我 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/
1 XCFOX 1 天前 |
2 lynchuh 1 天前 牛,学到了! |
4 jspatrick 1 天前 分享下我项目内的常见写法,这是表格相关的功能,几乎完全是 v2 的迁移版... ```Javascript const state = reactive({ loading: false, list: [], searchParams: { department: null, company: null, vehicleType: [], thisWeek: false, thisMonth: false, thisYear: false, startTime: computed(() => { if (!state.searchParams.time) return undefined; const startTime = state.searchParams.time[0]; return dayjs(startTime).startOf('day').format('YYYY-MM-DD HH:mm:ss'); }), endTime: computed(() => { if (!state.searchParams.time) return undefined; const endTime = state.searchParams.time[1]; return dayjs(endTime).endOf('day').format('YYYY-MM-DD HH:mm:ss'); }), time: [dayjs().startOf('month').forat('YYYY-MM-DD'), dayjs().endOf('day').format('YYYY-MM-DD')] }, options: { department: [], company: [], vehicleType: [] }, columns: hooks.useDefaultColumns([]), pagination: hooks.usePagination(() => state.search()), selectTimeMode(idx) { }, async search() { } }); ``` |
5 jspatrick 1 天前 |
7 duuu 1 天前 楼主的 useClient 其实就是我们常用的 Composable 的写法,只是在 return 里套了一层 reactive 。好处暂时看来是用的地方不用写.value 了。但是我感觉这样写反而会有心智负担,因为简单从代码里看 name ,和 greeting 的用法都是要.value 的,如果用了 useClient 后,client.greeting 和,client.name 都不用.value 反而在每次写的时候要思考一下。如果这种写法在团队里没有形成规范的话,也会让同事调用你的代码写起来很困惑 |
9 jspatrick 1 天前 @duuu #8 其实就是抽离不抽离的关系,如果文件复杂度上升,就抽出去做成 hooks 来用,如果只是简单的页面,这么写还是有好处的,所有的表单逻辑其实都被写在了 state 里,这整个 state 其实就是 hooks 本来要导出的东西,关注点也不会被其他 hooks 打断,并不是页面全被塞进 state ,而是某个业务相关的东西被单独做成一个 state ,一个页面也可能有多个不同业务的 state |
12 lizhenda 1 天前 这不就是 vue3 推荐的使用方法么 |
13 UnluckyNinja 1 天前 这其实就是 composable 的用法,但官方指南不建议在 composable 函数里对返回值用 reactive 包装,这样会导致解构语法响应性不正确。 比如你这个例子,如果使用者写 `const { name } = useClient()`,name 就会失去响应性。 官方的推荐做法是返回 ref 作为返回对象的属性,如果调用方想使用整体响应性并免除.value ,可以自己用 reactive 包装。 详见 https://cn.vuejs.org/guide/reusability/composables , 大量 composable 参考可以浏览 VueUse https://vueuse.org/ |
14 mizuhashi OP @UnluckyNinja 原文有提到用 reactive 包,我知道官方推的返回 ref 。不於 domain object 我想要解,就是想要它的封性,如果解了就都散了 |
15 Ketteiron 1 天前 @UnluckyNinja 官方文档这么写问题很大,似乎是暗示 return 一个 reactive 会丢失响应式,我第一次看文档时也是这么认为的。实际并不会,因为返回的是代理对象,只有对代理对象进行解构才会丢失响应式。 我想没人会 return obj ,正常都是 return { obj } ref x,y 和 reactive ({x,y}) 是等价的两种写法,只是后者不能解构 const {obj:{x,y}} = useXxx() 我想也没人这么闲用嵌套解构语法 文档只需说不建议返回 reactive 对象就行了,初学者可能会以为 {reactive()} 也是不行的。 |
16 UnluckyNinja 1 天前 @mizuhashi #14 只要学 vue 之前已经知道 JS 的解构语法,应该不会搞混返回 XX 对象和返回嵌套的 XX 对象的区别 |
17 UnluckyNinja 1 天前 @UnluckyNinja #16 回错了,想回的是 #15 楼 |
18 riceball 16 小时 25 分钟前 你是否真的需要对象中的每一个属性都 reactive?是否存在不需要交互的属性? |