Vue3 hooks 的问题

2021-08-20 14:35:41 +08:00
 17681880207

1 、因为很多页面都需要用到表格,所以我抽取了表格的逻辑到一个叫 useCommonTable.ts 的文件中,大概如下:

// ...省略无关代码
export default function (url) {
   const isLoading = ref(false)
   const tableData = ref([])
   const commonTableConfig = reactive({
     // ...
   })
   
   const getTableData = () => {
   	 // ...
   }
   
   return {
      isLoading,
      tableData,
      commonTableConfig,
      getTableData
   }
}

在使用的时候,一般就是如下:

setup() {
  const {
    isLoading,
    tableData,
    commonTableConfig,
    getTableData
  } = useCommonTable('url')
  
  return {
    isLoading,
    tableData,
    commonTableConfig,
    getTableData
  }
}

但是好死不死,突然有一个页面有 2 个表格,然后逻辑也一样,那我解构就重名了

setup() {
  // 表格 1
  const {
    isLoading,
    tableData,
    commonTableConfig,
    getTableData
  } = useCommonTable('url1')
  // 表格 2
  const {
    isLoading,
    tableData,
    commonTableConfig,
    getTableData
  } = useCommonTable('url2')
  
  return {
    isLoading,
    tableData,
    commonTableConfig,
    getTableData
  }
}

所以这种情况应该如何使用啊?我目前是

setup() {
  // 表格 1
  const useTable1 = useCommonTable('url1')
  // 表格 2
  const useTable2= useCommonTable('url2')
  
  return {
    isLoading1: useTable1.isLoading,
    tableData1: useTable1.tableData,
    commonTableConfig :useTable1.commonTableConfig,
    getTableData1: useTable1.getTableData,
    isLoading2: useTable2.isLoading,
    tableData2: useTable2.tableData,
    commonTableConfig :useTable1.commonTableConfig,
    getTableData2: useTable2.getTableData
  }
}

感觉这种导入方式有点啰里八嗦的。。。不知道各位大神是如何做的?能否教教小弟。。。

2 、关于 hooks 之间的调用

// hook1.ts
export default function() {
  const getStudentDetails = (studentId) => {
    // ...
  }
}

// hook2.ts
export default function() {
  const getClassDetails = async () => {
     const studentIds = await self.$axios.get('...')
     // 这里希望调用 hook1.ts 中的方法
     // getStudentDetails(studentIds[0])
  }
}

如果使用 callback 方式,在 hook2.ts 中传入的话,会导致 setup 中的引入必须有先后关系:

setup() {
  const {getStudentDetails} = useHook1()
  const {getClassDetails} = useHook2(getStudentDetails)
  
  return {
    // ...
  }
}

大哥们能教教小弟吗?新手勿喷,感谢大家!

2487 次点击
所在节点    程序员
21 条回复
gkinxin
2021-08-20 14:41:53 +08:00
个人认为没有问题,结构重名其别名就行。
silk
2021-08-20 14:42:52 +08:00
我觉得 loading 状态单独写 hook 然后 loading 状态跟表格绑定到一起是一个组件
silk
2021-08-20 14:45:07 +08:00
还有你是写 hook 上瘾么 感觉没必要。vue 就老老实实 写流水账就行了
17681880207
2021-08-20 14:47:15 +08:00
@silk 倒也不是上瘾,上面的问题只是我碰到问题之后的一个临时的一个 demo,想拿出来问问...
sjhhjx0122
2021-08-20 15:02:07 +08:00
那 useCommonTable 应该封装到 table 组件去,每个页面都要写一次这个 hooks 其实也蛮多此一举的
Danswerme
2021-08-20 15:07:06 +08:00
问题 1 我也好奇怎么解决。问题 2 的话,我目前也用的 callback 方式。如果 setup 里用不到 useHook1 解构出来的其他部分,那就在 hook2.ts 中直接引入 hook1.ts ,setup 里也就不用引入了 hook1.ts 。

前两天我也刚用 vue3 撸了一个瀑布流相册的 DEMO,里面就这么干的。


https://github.com/vhvy/vue3-waterfall
shilianmlxg
2021-08-20 16:06:48 +08:00
@Danswerme 仰望大佬~~~~
David1119
2021-08-20 16:16:34 +08:00
这么啰嗦。。。哪位大佬仿照 react-query 撸个 vue-query ?
John60676
2021-08-20 16:20:33 +08:00
@David1119 这不巧了么
vue-request ⚡️ 一个能轻松帮你管理请求状态(支持 SWR,轮询,错误重试,缓存,分页等)的 Vue 3 请求库
仓库地址: https://github.com/AttoJS/vue-request
shakukansp
2021-08-20 16:25:52 +08:00
@sjhhjx0122
这是 UI 组件和使用组件的逻辑的分离

比如一个 table 可能有很多功能,一个页面可能用到其中几个,另一个页面用到另外几个,其中有几个是需要受控的,你不可能全部封装到组件内部,需要自由组合组件提供的 props 。然后这些组合还要可以复用,因为 A/B/C/D 页面需要用组合 A,E/D/F 需要组合 B,G/H 需要组合 C 。


@David1119

简单看着 swr 的 api 写了一个,vue2 vue3 的 vca 通用
https://github.com/MinatoHikari/v-demi-request
ccyu220
2021-08-20 16:44:33 +08:00
上面的都说错了,这个是有解决方法的。
当初我也封装了表格复用。
具体方法,你在 hooks 里面定一个 register 方法,并用 getCurrentInstance 这个方法获取 uid 来做区分就好了。
这样你同个页面有 10 个相同的表格都没关系。
UnluckyNinja
2021-08-20 17:23:38 +08:00
第一个问题表示你该复用组件了……不复用都挤在父组件自然会遇到这个问题
ccraohng
2021-08-20 17:27:39 +08:00
全是模板代码。。。。
antd 的 pro table 设计挺好的。

这种 table 设计,不都是一个模式吗,抽成组件吧
shakukansp
2021-08-20 17:48:09 +08:00
@ccyu220 没看懂,两个组件放一个页面组件里那 getCurrentInstance 不都是同一个页面组件?

楼主的前提肯定是组件要是受控的,在父组件用 props 控制
suzic
2021-08-20 17:48:31 +08:00
个人觉得没什么问题,解构的时候直接 cont {a: a1}=usexxx()就好了
shakukansp
2021-08-20 17:52:11 +08:00
问题 1 你可能可以试试 hooks 里面返回数组……,这样就不用映射重命名
不过有一个问题是没提示了
summerLast
2021-08-20 17:53:28 +08:00
@Danswerme 第一种是不是可以尝试直接封装一个 CommonTable 的组件呢 useCommonTable 在 CommonTable 中使用 <CommonTable :url="url" .../>
summerLast
2021-08-20 17:56:23 +08:00
还有一种方式 就是不对 返回的数据展开 在使用的地方再展开
summerLast
2021-08-20 17:59:21 +08:00
@shakukansp 这个其实就是抽象复用的问题 当相同的代码逻辑出现多次以后要不要抽象出来 什么时候抽象 组件也是如此
shakukansp
2021-08-20 18:04:57 +08:00
@summerLast hooks 就是为了少用高阶组件啊

这么抽象又变成用很多 hoc 去复用了

既然用 vca 了就把一些 props 也写进 hooks,然后复用的时候直接在原生组件用 v-bind 绑定所有需要的属性即可

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/797017

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX