V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
17681880207
V2EX  ›  程序员

Vue3 hooks 的问题

  •  
  •   17681880207 · 57 天前 · 1379 次点击
    这是一个创建于 57 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 {
        // ...
      }
    }
    

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

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

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


    https://github.com/vhvy/vue3-waterfall
    shilianmlxg
        7
    shilianmlxg   57 天前
    @Danswerme 仰望大佬~~~~
    David1119
        8
    David1119   57 天前
    这么啰嗦。。。哪位大佬仿照 react-query 撸个 vue-query ?
    John60676
        9
    John60676   57 天前
    @David1119 这不巧了么
    vue-request ⚡️ 一个能轻松帮你管理请求状态(支持 SWR,轮询,错误重试,缓存,分页等)的 Vue 3 请求库
    仓库地址: https://github.com/AttoJS/vue-request
    shakukansp
        10
    shakukansp   57 天前
    @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
        11
    ccyu220   57 天前
    上面的都说错了,这个是有解决方法的。
    当初我也封装了表格复用。
    具体方法,你在 hooks 里面定一个 register 方法,并用 getCurrentInstance 这个方法获取 uid 来做区分就好了。
    这样你同个页面有 10 个相同的表格都没关系。
    UnluckyNinja
        12
    UnluckyNinja   57 天前 via Android
    第一个问题表示你该复用组件了……不复用都挤在父组件自然会遇到这个问题
    ccraohng
        13
    ccraohng   57 天前
    全是模板代码。。。。
    antd 的 pro table 设计挺好的。

    这种 table 设计,不都是一个模式吗,抽成组件吧
    shakukansp
        14
    shakukansp   57 天前
    @ccyu220 没看懂,两个组件放一个页面组件里那 getCurrentInstance 不都是同一个页面组件?

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

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

    既然用 vca 了就把一些 props 也写进 hooks,然后复用的时候直接在原生组件用 v-bind 绑定所有需要的属性即可
    sjhhjx0122
        21
    sjhhjx0122   56 天前
    @shakukansp 我的意思是他应该用这个 hook,封装一个基础 table 组件,复用这个组件,因为 loading,分页,请求都是基本功能,当封装的组件不满足他的基本需求时候,再用普通的 table 标签+hook 配合其他 hook,就像 ahooks 有 useAntdTable 的 hook,为什么 protable 还封装了这么多功能
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1980 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 11:26 · PVG 19:26 · LAX 04:26 · JFK 07:26
    ♥ Do have faith in what you're doing.