Vue.js在复杂信息流场景下的实践
作者:互联网
Vue.js在复杂信息流场景下的实践
常见的 hybird 页面
- 常见的 UGC 类的 PC 网页
这类页面都会承载着多个信息流列表,本文就针对这类复杂信息流页面进行梳理,给出我在做了无数次这类页面后的最佳实践总结。
你可以查看最终 demo 效果: https://falstack.github.io/vue-hybird-best-practices/
demo 的代码仓库: https://github.com/falstack/vue-hybird-best-practices
实践步骤 第一步:我们需要一个 Tab 组件作为承载信息流的容器 这个 tab 组件至少要满足以下两个场景:切换 Tab 时的渐变动画
- 滑动时的手指跟随
因为这些 feature 能够让我们的页面效果尽可能的接近原生,因此专门把它抽象成一个组件:
v-switcher:一个强大的 Tab 组件,GitHub 地址: https://github.com/falstack/v-switcher
我们注意到页面顶部的这个图片轮播组件与 Tab 组件的区别仅仅是:「能否自动滑动」。因此我们在 v-switcher 里增加了几行代码来兼容图片轮播功能。
第二步:我们需要一个方便的状态管理工具来存储信息流的数据和状态什么意思呢?仔细思考一下对于每一个信息流列表,它都会有以下这几个状态:v-switcher 的实现还兼容了很多场景,可以查看 github 的 readme 来了解。
- loading(加载中)
- nothing(列表为空)
- error(列表加载出错)
- fetched(已经向服务端发起过请求的列表)
noMore(列表已加载完,没有更多了)
除此之外我们还要根据列表的长度在第一屏展示特殊的 loading(通常为骨架屏)或 error (通常为大图),而在非第一屏的情况下展示其它 UI 样式。
当我们点击 Tab 切换到另一个列表的时候,上一个列表的状态要正确的维持,下一个列表和上一个列表的状态要分离开,如果还需要下拉刷新、筛选排序等,如果不抽象一个数据层出来,那这个代码是真的难看,相信经常做这类页面的同学都深有体会。
为了对信息流的数据和状态进行一个完美的管理,我们又提供了另一个组件:
vue-mixin-store:一个专门做列表状态管理的组件,GitHub地址: https://github.com/falstack/vue-mixin-store
vue-mixin-store 是依赖于 vuex 的,它提供了很多的 API 让列表的 CURD 变的非常方便,通过它你可以让绝大多数信息流的开发都变成复制粘贴,文档地址: https://falstack.github.io/vue-mixin-store/
第三步:我们需要对信息流列表做惰性渲染一开始做这个优化,我是想使用 vue-virtual-scroll-list 这个库的,但这个库有几个地方无法满足我的需求:所谓惰性渲染,就是指在列表里只保留视口内的 DOM,视口之外的 DOM 不展示,在列表滚动的时候,我们通过 JS 来计算要渲染哪些 DOM,达到优化内存的目的。
- 无法兼容 better-scroll
仅支持单列的列表,无法支持瀑布流
因此这个库虽然很好,但对我来说它的应用场景“受限”,所以没办法只好自己写了一个:
vue-flow-render:一个列表惰性加载组件,GitHub 地址: https://github.com/falstack/vue-flow-render
其实和 vue-virtual-scroll-list 对比区别不是很大,只是我将“滚动”的行为从组件中剥离出去,只保留了滚动的结果,因此使用该组件的时候它需要一个父容器来分发scroll
事件。
支持瀑布流也只是在计算 DOM 位置的时候根据 props 做了不同的 case 处理,都很简单。
但它可以应用在更广的场景中。
至此我们的页面无论是代码整洁度还是性能都有了一定的保障(
v-switcher
针对性能也做了很多优化、vue-flow-render
也是尽可能通过少的计算量来实现的惰性加载)
于是我们就开心的写完代码提交给了测试的同事验收,但发现好像还有点问题?
具体是什么问题呢,相信经常做移动端开发的同学都有遇到过这个问题:-webkit-overflow-scrolling: touch 导致的页面锁死。
遇到这个问题真是难受,网上的解决方法五花八门都达不到效果。
因为毕竟做了很久的前端开发,所以我对这个 bug 是早就知道的,因此在一开始寻找惰性加载组件时就希望能够与 better-scroll 搭配使用,因为 better-scroll 是可以解决页面锁死问题的。
于是我们愉快的使用起了 better-scroll 又提测了。
然后发现又有点不对:
better-scroll 在 Android 设备上的体验,真的很不好,特别是当页面里的数据量很大,并且有很多个 tab(需要很多个 better-scroll 实例)的时候。
而且在其他项目中尝试使用 better-scroll 会在复杂场景下(路由切换 + 异步请求等)会导致一些机型(iPhoneX)的偶现 bug。
因此在测试同学的强烈要求下,我们也无法使用 better-scroll 了。
但这个问题还是得解决啊,于是我们在寻找专门解决页面锁死的库,终于是找到了一个:iNoBounce,尝试了一下真的解决了问题。
但怎么说呢,这个库用起来并不怎么舒服,把它加到我们的最佳实践里好像还缺了一些分量,我们需要加强它。
第四步:我们需要一个专门处理滚动行为的组件需要这个组件的原因是:- 我们需要解决 iOS 页面锁死的问题。
- 我们需要分发 scroll 事件给 vue-flow-render。
我们有更多的场景需要 onTop、onBottom、onRefresh 等事件
因此我们提供了另一个组件:
h5-vue-scroller:一个处理 iOS 页面锁死和分发滚动事件的组件,GitHub 地址: https://github.com/falstack/h5-vue-scroller
一个组件无法解决所有问题至此,我们的「Vue.js 在复杂信息流场景下的最佳实践」所需要的组件都已经给出来了,接下来就简单讲一下为什么要这么做。
虽然这篇文章介绍了四个组件搭配的结果,但并不代表着你需要在所有地方都同时使用它们。
在其他场景的最佳实践下会需要其他组件,这其中有一点是可以肯定的:我们的代码不能杂糅起来,必须要很好的分层,再去组件化。
我相信很多学习 Vue.js 的同学都看过下面这种图:
组件化开发
但在复杂场景下,又有多少人能把代码合理的抽象与组件化呢?
vue-mixin-store 的实现初衷就是因为我之前有一个同事列表从来不写 loading,也不做异常处理,页面代码里到处都是 DOM 操作,我实在是受不了了才写了这么个组件出来。
希望这篇文章能让你的开发变得简单,感谢阅读(记得 star 和遇到问题提 issue 给我)。
七夕福利解锁 80+ 极客时间课程,全方位提升技术水平和业务能力。扫描图上二维码,或点击“阅读原文”享受七夕特惠
标签:vue,信息流,列表,Vue,组件,js,scroll,页面 来源: https://blog.51cto.com/15057848/2566870