Vue.js在复杂信息流场景下的实践

Vue.js在复杂信息流场景下的实践




image.png

做者 | 刘磊编辑 | Yonie 前端开发者在作 web 业务需求时,经常要作不少重复性的工做。本文将从常见需求出发,一步步的解构复杂场景,把最经常使用的组件抽离出来,回归代码的分层与组件化,避免机械的重复编码。   背景  常常作业务的前端同窗确定遇到过这样的业务场景:
  • 常见的 hybird 页面前端

image.png

  • 常见的 UGC 类的 PC 网页
  • image.png

这类页面都会承载着多个信息流列表,本文就针对这类复杂信息流页面进行梳理,给出我在作了无数次这类页面后的最佳实践总结。vue

你能够查看最终 demo 效果: https://falstack.github.io/vue-hybird-best-practices/git

demo 的代码仓库: https://github.com/falstack/vue-hybird-best-practicesgithub

实践步骤 第一步:咱们须要一个 Tab 组件做为承载信息流的容器 这个 tab 组件至少要知足如下两个场景:
  1. 切换 Tab 时的渐变更画web

  2. image.png

  1. 滑动时的手指跟随
  2. image.png

由于这些 feature 可以让咱们的页面效果尽量的接近原生,所以专门把它抽象成一个组件:
vuex

v-switcher:一个强大的 Tab 组件,GitHub 地址: https://github.com/falstack/v-switcher异步

咱们注意到页面顶部的这个图片轮播组件与 Tab 组件的区别仅仅是:「可否自动滑动」。所以咱们在 v-switcher 里增长了几行代码来兼容图片轮播功能。ide

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/

 第三步:咱们须要对信息流列表作惰性渲染

所谓惰性渲染,就是指在列表里只保留视口内的 DOM,视口以外的 DOM 不展现,在列表滚动的时候,咱们经过 JS 来计算要渲染哪些 DOM,达到优化内存的目的。

一开始作这个优化,我是想使用 vue-virtual-scroll-list 这个库的,但这个库有几个地方没法知足个人需求:
  1. 没法兼容 better-scroll
  2. 仅支持单列的列表,没法支持瀑布流

所以这个库虽然很好,但对我来讲它的应用场景“受限”,因此没办法只好本身写了一个:

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,尝试了一下真的解决了问题。

但怎么说呢,这个库用起来并不怎么舒服,把它加到咱们的最佳实践里好像还缺了一些份量,咱们须要增强它。

 第四步:咱们须要一个专门处理滚动行为的组件须要这个组件的缘由是:
  1. 咱们须要解决 iOS 页面锁死的问题。
  2. 咱们须要分发 scroll 事件给 vue-flow-render。
  3. 咱们有更多的场景须要 onTop、onBottom、onRefresh 等事件

所以咱们提供了另外一个组件:

h5-vue-scroller:一个处理 iOS 页面锁死和分发滚动事件的组件,GitHub 地址: https://github.com/falstack/h5-vue-scroller

至此,咱们的「Vue.js 在复杂信息流场景下的最佳实践」所须要的组件都已经给出来了,接下来就简单讲一下为何要这么作。

一个组件没法解决全部问题

虽然这篇文章介绍了四个组件搭配的结果,但并不表明着你须要在全部地方都同时使用它们。

在其余场景的最佳实践下会须要其余组件,这其中有一点是能够确定的:咱们的代码不能杂糅起来,必需要很好的分层,再去组件化。

我相信不少学习 Vue.js 的同窗都看过下面这种图:image.png

组件化开发

但在复杂场景下,又有多少人能把代码合理的抽象与组件化呢?

vue-mixin-store 的实现初衷就是由于我以前有一个同事列表历来不写 loading,也不作异常处理,页面代码里处处都是 DOM 操做,我实在是受不了了才写了这么个组件出来。

但愿这篇文章能让你的开发变得简单,感谢阅读(记得 star 和遇到问题提 issue 给我)。

 七夕福利

解锁 80+ 极客时间课程,全方位提高技术水平和业务能力。扫描图上二维码,或点击“阅读原文”享受七夕特惠

相关文章
相关标签/搜索