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+ 極客時間課程,全方位提高技術水平和業務能力。掃描圖上二維碼,或點擊「閱讀原文」享受七夕特惠

相關文章
相關標籤/搜索