Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

在使用 vue-request 之后的一些改进建议 #39

Closed
keuby opened this issue Apr 26, 2021 · 8 comments
Closed

在使用 vue-request 之后的一些改进建议 #39

keuby opened this issue Apr 26, 2021 · 8 comments

Comments

@keuby
Copy link

keuby commented Apr 26, 2021

最近我们做了个新项目选用了 vue3,也使用了 vue-request 这个库,目前使用一个多月了,有一些建议我觉得可以讨论一下

暴露更多的内部 API和类型

目前我们项目使用这个库,都是无法直接使用的,需要进行二次封装,这个因为发送请求的多变性而没办法避免的,进行二次封装的时候我遇到了一些问题,有下面一些建议。

  1. 把一些类型声名 例如 BaseOption 这种在 index.ts 里面暴露出来,方便引入
  2. 把尽可能多的常量(例如QUERY_DEFAULT_KEY),内部方法(例如useAsyncQuery)在 index.ts 中暴露出来,方便自己实现一些自定义的逻辑
  3. 提供一些全局的 hooks 用于实现一些自定义的逻辑,例如只要有一个请求变为 loading 的时候,触发一个比如叫 beforeAnyLoading 的钩子,所有请求都加载完触发一个 afterAllLoaded 钩子,可以很方便的实现一些例如

说实话我感觉用这个库的时候,二次封装的可能性非常大,我觉得作者大大可以多考虑一下二次封装的便捷性。

---------------------------分割线,下面可能是一些废话,作者大大可以考虑跳过,主要结论都在上面--------------------------

useRequest 的封装

我希望在发送请求的时候,如果请求时间过长超过 loadingDelay 的值的时候,在全局显示一个加载,遇到我问题如下

  1. 我需要对 useRequest 的第二个参数进行扩展,例如再传入一个参数用于设置 loading 的提示语,那么需要把例如 BaseOptions进行扩展,但是导入的时候,我得从 vue-request/dist/types/core/config 里面进行导入,这很不友好。希望可以在 index.ts 直接导出
  2. 我无法再 loading 变为 true 之前和 loading 变为 false 之前做一些操作,目前我只能使用 watchEffect 来监听 loading 的变化来实现这个功能。

useLoadMore 的封装

因为加载更多这个逻辑,一个系统的类型肯定是一样的,如果不进行二次封装,那么每次使用的时候都会写一大堆类型声明,这样肯定不合适。二次封装的时候一些问题如下

  1. 导入类型太麻烦(x2 [手动狗头.png]),上面已经提到了
  2. formatResult 这个东西类型推导有问题,我二次封装的时候直接把这个功能砍掉了。而且我觉得这个功能意义不大,format 这个操作完全可以放到传入的 service 方法里面来做,不知道作者有没有其他的考虑[手动狗头.png]。
  3. loadingMore 在 reload 的时候是 false,这样的话就 reload 的时候,van-list 就没有 loading 动画了,所以就自己撸了一个,从而引出了下面一系列问题。(因为项目上线在即没办法和作者大大讨论再改,也不想给作者大大压力,咱们自己的需求还是自己解决,不过接口都是一样的,要是作者大大后续考虑支持的话,我直接把内部实现换成作者大大的 useLoadMore 就好了)

-----------下面是自己封装 useLoadMore 出现的问题----------

  1. 因为作者大大没有暴露 useAsyncQuery,所以就只能基于 useRequest 了(强烈建议多暴露一写内部方法)
  2. 开始一切顺利,不过在 reload 方法的时候,需要对数据重置,直接对 useRequest 返回值解构出来的 data 进行复制为 null 是不起作用的(看了源码发现 data 的值总是 latestQuery.value.data,赋值还是会被改回来),然后看到好像有个 reset 但是发现 useRequest 这个方法没导出 reset,然后想通过 queries 重置发现 QUERY_DEFAULT_KEY 这个常量没导出,最后我直接用 __QUERY_DEFAULT_KEY__ 这个玩意儿来获取默认 query,调用 mutate 来重置了。(饶了好大一个弯儿)。
  3. 如果暴露出 useAsyncQuery,上面那一步的东西都不存在

hooks 的设想

对于发送请求这个需求,应该会有很多的奇奇怪怪的需求,如果可以抽象出来一些公用的 hooks,应该可以解决很多自定义的需求,例如上面我对 useRequest 进行封装,在请求超过 loadingDelay 的时候,全局显示 loading,如果有一个 hook,只要有一个请求变为 loading 的时候,触发一个比如叫 beforeAnyLoading 的钩子,然后我就给他显示一个 loading 动画,然后有个 afterAllLoaded,然后我把 loading 动画关掉,这就很完美。

@John60676
Copy link
Member

把一些类型声明 例如 BaseOption 这种在 index.ts 里面暴露出来,方便引入

这个会在内部的类型重构完之后导出给用户使用的,目前内部的类型声明还有点乱,挺多地方值得优化一下的

把尽可能多的常量(例如QUERY_DEFAULT_KEY),内部方法(例如useAsyncQuery)在 index.ts 中暴露出来,方便自己实现一些自定义的逻辑

useAsyncQuery 原本计划就是导出来给开发者用于二次开发的,可能后面给忘了。目前在做兼容 Vue 2,顺便再捋一下整体的代码,等这部分做完了,就重新把 useAsyncQuery 给导出来。

提供一些全局的 hooks 用于实现一些自定义的逻辑,例如只要有一个请求变为 loading 的时候,触发一个比如叫 beforeAnyLoading 的钩子,所有请求都加载完触发一个 afterAllLoaded 钩子,可以很方便的实现一些例如

至于这个问题,暂时还没有这个计划。因为这样做一方面会不太稳定,而且状态维护起来比较困难,另一方面就是我们的想法是库的底层简单点好,这样上层使用的话就会更加灵活。你提出的这个问题,上层用计数器应该就可以实现了。

formatResult 这个东西类型推导有问题,我二次封装的时候直接把这个功能砍掉了。而且我觉得这个功能意义不大,format 这个操作完全可以放到传入的 service 方法里面来做,不知道作者有没有其他的考虑[手动狗头.png]。

这个具体是什么问题,可以开个issue详细聊一下。

loadingMore 在 reload 的时候是 false,这样的话就 reload 的时候,van-list 就没有 loading 动画了,所以就自己撸了一个,从而引出了下面一系列问题。(因为项目上线在即没办法和作者大大讨论再改,也不想给作者大大压力,咱们自己的需求还是自己解决,不过接口都是一样的,要是作者大大后续考虑支持的话,我直接把内部实现换成作者大大的 useLoadMore 就好了)

这个我当初在实现时也有考虑过,但是如果再 reload 时也触发的话,那 loadingMore 和 'loading' 就没有差别了。所以还是保持了 loadingMore 只会在 loadMore 触发时响应。至于你这个需求,我想是不是可以用 refresh 来替代 reload 呢。

非常感谢你选择使用 VueRequest,希望我们的库能在你们的项目中提供到帮助。可能你上面提的我们不一定都能帮你实现到(因为我们还要考虑更多的应用场景),但是你的每一个建议都对我们有很大的帮助,毕竟这是实际开发中遇到过的问题,是我们开发库时忽略了的问题。

@keuby
Copy link
Author

keuby commented Apr 28, 2021

这个我当初在实现时也有考虑过,但是如果再 reload 时也触发的话,那 loadingMore 和 'loading' 就没有差别了。所以还是保持了 loadingMore 只会在 loadMore 触发时响应。至于你这个需求,我想是不是可以用 refresh 来替代 reload 呢。

感觉这个和 loading 还是有区别的,loading的话其实在 refresh 的时候也会变为 true,但是 loadingMore 是不会的,如果可以支持的话,为了防止 breaking change 的话,可以考虑添加一个配置参数来支持

至于这个问题,暂时还没有这个计划。因为这样做一方面会不太稳定,而且状态维护起来比较困难,另一方面就是我们的想法是库的底层简单点好,这样上层使用的话就会更加灵活。你提出的这个问题,上层用计数器应该就可以实现了。

这个我觉得上层实现起来难度不大,库底层实现这个东西确实不是太合适,不过我觉得可以提供一些更方便的接口来方便二次封装,例如对于全局显示 loading 的封装,由于 loadingDelay 这个配置的原因,我不知道具体什么时候 loading 会变成 true,所以只能通过 watchEffect 来监听 loading 的变化,从而实现对 全局 loading 效果的显示和隐藏。不知道有没有更好的实现方式

这个具体是什么问题,可以开个issue详细聊一下。

差不多还是类型推导的问题,在使用 formatResult 的情况下,formatResult 的 参数的类型会变成 any,返回值可以正常推断成功,这个我在另一个 issue 里面有看到类似的问题,后续弄一段代码复现一下,新开一个的 issue 讨论下吧

@keuby
Copy link
Author

keuby commented Apr 28, 2021

至于你这个需求,我想是不是可以用 refresh 来替代 reload 呢。

refresh 代替 reload 其实不是很好,在一个下拉刷新,上拉加载更多的这个场景下,refreshing 绑定到了下拉刷新的 loading 状态,loadingMore 绑定到了 上拉加载更多的 loading 状态,那么使用 refresh 来做刷新的话,vant 下拉刷新组件是的 loading 是不会显示的(PullRefresh 的 loading 在没有下拉触发的时候,被定位到了容器外面,容器有个 overflow hidden 属性给隐藏了,显示不出来,需要下拉的时候才会出现)。所以当 reload 的时候,数据被清空,会出现界面是有一段时间空白,而没有任何加载信息反馈给用户的情况

@John60676
Copy link
Member

John60676 commented May 6, 2021

至于你这个需求,我想是不是可以用 refresh 来替代 reload 呢。

refresh 代替 reload 其实不是很好,在一个下拉刷新,上拉加载更多的这个场景下,refreshing 绑定到了下拉刷新的 loading 状态,loadingMore 绑定到了 上拉加载更多的 loading 状态,那么使用 refresh 来做刷新的话,vant 下拉刷新组件是的 loading 是不会显示的(PullRefresh 的 loading 在没有下拉触发的时候,被定位到了容器外面,容器有个 overflow hidden 属性给隐藏了,显示不出来,需要下拉的时候才会出现)。所以当 reload 的时候,数据被清空,会出现界面是有一段时间空白,而没有任何加载信息反馈给用户的情况

reload 的话。可以考虑再加个 reloading,因为确实也没其他途径能区分是 reloading 还是 loading。不过我想知道有什么场景下需要用到 reload

这个我觉得上层实现起来难度不大,库底层实现这个东西确实不是太合适,不过我觉得可以提供一些更方便的接口来方便二次封装,例如对于全局显示 loading 的封装,由于 loadingDelay 这个配置的原因,我不知道具体什么时候 loading 会变成 true,所以只能通过 watchEffect 来监听 loading 的变化,从而实现对 全局 loading 效果的显示和隐藏。不知道有没有更好的实现方式

如果做全局 loading 的话,其实不用管 VueRequest 返回的 loading。如果要封装的话,在 axios 的 interceptors.request 拦截器里面做个计数器,然后在 axios 的 interceptors.response 里面做后续处理就好了。

或者我们这边也可以考虑一下,有没有好的办法能够底层也把这部分事情给处理了。主要还是看需要的人多不多😂

@keuby
Copy link
Author

keuby commented May 6, 2021

reload 的话。可以考虑再加个 reloading,因为确实也没其他途径能区分是 reloading 还是 loading。不过我想知道有什么场景下需要用到 reload

例如列表上方有一个搜索框,这个时候输入关键字搜索列表内容。如果使用 refresh 的话,因为不存在下拉无法显示下拉动画,加载更多也因为在列表顶部所以也无法显示(上拉加载的动画在列表最底部),所以只能清空列表,然后重新加载数据,通过 loadingMore 的加载更多动画给予用户一个反馈。否则就只能再加额外的逻辑去另外实现一个加载动画来通知用户正在搜索。

如果做全局 loading 的话,其实不用管 VueRequest 返回的 loading。如果要封装的话,在 axios 的 interceptors.request 拦截器里面做个计数器,然后在 axios 的 interceptors.response 里面做后续处理就好了。

这个方式我也有考虑过,但是后面放弃了。主要的原因是某些情况下因为有其他的loading显示规则而需要在全局的地方显示loading动画,就会比较难搞,还需要再想办法对于是否在 axios 发请求的时候显示loading做额外的处理。比如 列表下拉刷新这个场景就不需要再全局显示loading,因为list组件已经有loading的交互效果了。

@John60676
Copy link
Member

#41
#42

上面讨论的点已加入计划

@John60676
Copy link
Member

#41
#42

上面讨论的点已加入计划

v1.2.0 已发布

@keuby keuby closed this as completed Jun 3, 2021
@AllenForward
Copy link

最近在使用过程中同样遇到一样的问题,希望能暴露出一些方法和类型方便二次封装.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants