凡人修React|新手練氣築基必備! 抖音商城[商品資訊卡元件]開發

語言: CN / TW / HK

theme: healer-readable

持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第1天,點選檢視活動詳情

前言

React - 宣告式:React 使建立互動式 UI 變得輕而易舉。為你應用的每一個狀態設計簡潔的檢視,當資料改變時 React 能有效地更新並正確地渲染元件。 - 元件化:建立擁有各自狀態的元件,再由這些元件構成更加複雜的 UI。元件邏輯使用 JavaScript 編寫而非模版,因此你可以輕鬆地在應用中傳遞資料,並使得狀態與 DOM 分離。 本次通過開發抖音商城商品資訊列表元件,走進React的懷抱。
不多說,先看效果gh-pageshttps://hunag-mouren.github.io/dy_mall/
再看專案架構

63.png

1. 元件設計與功能需求

1.1 元件設計

首先將商品資訊卡列表元件細化,分為頭部tabs切換部分資訊卡列表部分,其中資訊卡列表部分包含有商品資訊卡項直播資訊卡項影片資訊卡項,且各項資訊卡項包含兩種狀態,分別為資料載入前的狀態資料載入後的狀態。即: - 頭部tabs切換部分 - 商品資訊卡項 - 直播資訊卡項 - 影片資訊卡項

如下圖所示。 bing.png 基於以上我們有如下元件藍本的程式碼: 1.png

1.2 功能需求

就實際應用場景而言,有如下功能應當實現: - Tabs切換跟隨點選顯示高亮並激活 - 資訊卡列表部分跟隨tabs切換顯示相應內容 - 第一進入某個資訊卡資料載入時應當顯示資料載入前的狀態,後面再進入該項不再顯示資料載入前的狀態 - 圖片懶載入的實現 - 當滾動到底部後可以載入新的資料

2. 元件實現

2.1 Tabs切換部分實現

Tabs切換部分將使用antd-mobile中的Tabs元件來實現,其選項卡面板為Tabs.tab。其中本次涉及屬性有:

Tabs屬性 - activeKey:為當前啟用面板的key值 - onChange:切換面板時的回撥,傳入的引數為將被選中Tab的key值


Tabs.Tab屬性 - key:和Tabs的activeKey對應 - title:選項卡的標題名字 由以上可知,當我們選中的面板被啟用,則Tabs中的activeKey屬性值就會變成對應選中面板Tab的key值,憑此會為為Tab面板新增“adm-tabs-tab-active”的類名(如下圖所示),進而被選中時高亮。

2.png 那我們只需要把activeKey值修改為我們將選中的面板的key值就可以啟用它,這時我們就可以藉助onChange屬性,在回撥函式中修改activeKey的值。但是activeKey作為屬性不好在回撥函式中操作,那不妨利用一箇中間變數,修改中間變數的值,再把中間變數的值傳給activeKey。考慮到後續在切換面板時要顯示相應的內容,那麼我們這裡使用State Hook,利用useState()方法返回的state值作為中間變數以及更新state值的函式來修改該值,以達到更新activeKey值得目的,進而實現Tabs切換。實現程式碼如下。

6.png 考慮到我們當前定義的從useState()方法解構出來的[activityKey,setActivityKey]不僅僅只會在GoodCardList元件中被使用,我們應當將其放在父元件當中。於是我們通過父元件給子元件傳參,讓GoodCardList元件得到這些屬性。程式碼將修改如下。

4.png

5.png 至此Tabs頭部切換完成,效果如下。

chrome-capture-2022-5-28.gif

2.2 資訊卡列表部分實現

由上文可知資訊卡列表部分其實是由商品資訊卡項直播資訊卡項影片資訊卡項組成,就實際情況而言可視該三項內容為通用元件。這三項異曲同工,不妨就以商品資訊卡為例。這時我們需要進行資料請求,資料方面我們通過線上介面工具fastmock組織,fastmock可以讓你在沒有後端程式的情況下能真實地線上模擬 ajax 請求,實現前後端分離。然後我們通過axios進行請求資料,axios是一個基於promise 的 HTTP 庫。同時使用async函式與await操作符同步化獲取資料過程。 在src目錄下新建一個api資料夾,在其之下新建request.js檔案,該檔案用於做請求方面的工作,我們資料請求的程式碼就封裝在其中。

8.png

資料請求一般都在頁面級別元件,請求到的資料通過引數傳遞給子元件。這時我們就要請出Effect Hook,它可以告訴React元件需要在渲染後執行某些操作。React 會儲存你傳遞的函式(我們將它稱之為 “effect”),並且在執行DOM更新之後呼叫它。預設情況下,它在第一次渲染之後和每次更新之後都會執行。但我們可以通過給它的第二引數(是個陣列)來控制它,如果這個數組裡的內容在兩次重渲染之間沒有發生變化,就可以通知 React 跳過對這個effect 的呼叫;如果發生了改變就會再次對這個effect進行呼叫。那麼我們在切換不同面板時需要請求不同的內容,我們就可以把請求資料的過程放在Effect中,並通過前文的定義的State中的activityKey來實現面板切換時是否需要請求資料。

9.png

GoodsCardList元件內接收資料後,根據資料生成(map)資訊卡列表裡各項內容,同時別忘了在map列表裡的資料內容時,要給每一項新增一個獨一無二的key值
因為每當一個列表重新渲染時,React 會根據每一項列表元素的 key 來檢索上一次渲染時與每個 key 所匹配的列表項。如果 React 發現當前的列表有一個之前不存在的 key,那麼就會創建出一個新的元件。如果 React 發現和之前對比少了一個 key,那麼就會銷燬之前對應的元件。如果一個元件的 key 發生了變化,這個元件會被銷燬,然後使用新的 state 重新建立一。(這裡我在fastmock組織的資料中給每條資料都自動生成了一個獨一無key)

12.png

商品資訊卡項元件的實現

13.png

至此商品資訊卡列表元件開發過半,來看看目前效果。

11.gif

2.3 增加loading狀態

發現每次切換面板的時候,頁面需要過一段時間才會顯示內容,使用者體驗不好。這時由於資料還在請求中,資料請求完成後才渲染出該列表內容,那麼我們這時需要新增一個loading狀態,在資料請求數顯示loading狀態的頁面內容。

增加一個新的State Hook ,[loading,setLoading]=useState(false)來控制是否需要loading,[requestKey,setRequestKey]=useState([])來記錄某個面板是否被訪問過,訪問過後再訪問不會再出現loading狀態。

14.png

並給商品資訊卡項直播資訊卡項影片資訊卡項加入loading狀態時顯示的框架內容。其種loading狀態顯示的框架屏內容使用了antd-mobile的Skeleton,它可以在需要等待載入內容的位置提供一個佔位圖形組合。具體如下

15.png

看看現在的效果

88.gif

2.4 實現圖片懶載入

考慮實際應用場景,我們不妨在加上懶載入,當圖片未出現在可視區域是用佔位圖代替,進入可視區域顯示圖片 使用IntersectionObserver建立觀察器例項,通過檢查圖片是否出現在可視區域,來實現懶載入。 16.png

效果如下。

99.gif

2.5 滾動底部自動載入資料

實現滾動到底部自動載入更多資料 這是使用到antd-mobil的InfiniteScroll,它有如下屬性 - hasMore:是否還有更多內容 - loadMore:載入更多的回撥函式 - threshold:觸發載入事件的滾動觸底距離閾值,單位為畫素 使用者想看到新的資料時,可以上滑頁面自動載入資料。當 hasMore 屬性為 true 時,使用者頁面滾動到底部 threshold (預設為 250px)時無限滾動元件會呼叫定義的 loadMore 函式。程式碼如下:

55.png 並配和上文的requestKey來實現當首次進入某個面板未請求資料前不提供該滾動元件,否則在第一次進入某個面板時該滾動元件會先執行。來看下當前效果吧。

100.gif 可以看到當滾動到底部時會去請求資料,並將根據新資料建立新的資訊卡項,當然是通過資訊卡項中的key來決定是否要新建,像之前就建立好的資訊卡項在這次就不會新建了。

總結

至此該商品資訊列表元件開發就完成了,另外還有三個通用元件,商品資訊卡項元件直播資訊卡項元件影片資訊卡項元件。這四個元件在以後都會經常被用到的。接下來對本次元件開發過程進行總結

- State Hook:它讓我們在 React 函式元件上新增內部 state,通過useState()方法我們可以定義當前 state 以及更新 state 的函式。

- Effect Hook:它可以告訴 React 元件需要在渲染後執行某些操作。React 會儲存你傳遞的函式(我們將它稱之為 “effect”),並且在執行 DOM 更新之後呼叫它。預設情況下,它在第一次渲染之後和每次更新之後都會執行。但同時,我們可以給它的第二個引數傳入一個數組,當數組裡的內容發生改變時effectc才會再執行。

- key值:在map生成新的元件時,記得新增獨一無二的key,因為每當一個列表重新渲染時,React 會根據每一項列表元素的 key 來檢索上一次渲染時與每個 key 所匹配的列表項。如果 React 發現當前的列表有一個之前不存在的 key,那麼就會創建出一個新的元件。如果 React 發現和之前對比少了一個 key,那麼就會銷燬之前對應的元件。如果一個元件的 key 發生了變化,這個元件會被銷燬,然後使用新的 state 重新建立一份。

- styled-components:css in js 。styled-components 為您的樣式生成唯一的類名。您永遠不必擔心重複、重疊或拼寫錯誤。很難知道類名是否在您的程式碼庫中的某處使用。styled-components 讓它變得顯而易見,因為每一個樣式都與特定的元件相關聯。如果元件未使用(工具可以檢測到)並被刪除,則其所有樣式都會隨之刪除。根據元件的 props 或全域性主題調整元件的樣式簡單直觀,無需手動管理數十個類。本次就通過props將背景圖片自定義引數化傳入。

- antd-mobile:移動端的常用元件庫,比如本次用的Tabs,Skeleton,Space。用就對了。

  • font-awesome:Font Awesome 字型為我們提供可縮放向量圖示,它可以被定製大小、顏色、陰影以及任何可以用CSS的樣式。用就對了

Next

商品資訊卡列表元件開發完畢,下一步將會開始搭建商城主頁面,並將Router安排上。
本次專案地址 :https://github.com/hunag-mouren/dy_mall.git
gh-pages:https://hunag-mouren.github.io/dy_mall/