基於 React + TypeScript 的網易雲音樂

基於 React 實現的仿 iOS 客戶端網易雲音樂。css

項目地址:戳我react

在線地址:戳我(PC 瀏覽器需切換到移動端模式)git

移動端體驗:github

預覽

技術棧

  • React 16.3
  • TypeScript
  • Mobx + Redux
  • react-redux
  • react-router-v4
  • Scss

實現細節

目前只實現了上面四個頁面,可是整體的結構已經造成了,其餘頁面的添加只是時間上的問題 (實際上是懶),暫時沒有實現,下面是目前已實現的功能的細節:redux

局部狀態管理

像首頁的 banner 或者推薦歌單等,都是不會被共享的局部狀態,使用 Mobx 來進行請求的發起和狀態的管理。api

全局狀態

播放器的狀態是一個全局狀態,包括當前的播放列表,切歌,播放 / 暫停等,因此很天然的使用 redux 來進行管理,能夠清楚的掌握全部改變全局狀態的行爲。瀏覽器

TypeScript

儘管上手須要掌握一些語法,可是靜態類型與自動提示都能提供很大的幫助,在這個並不大的項目中我也體驗到了很大的幫助。可是要注意的是 TS 其實並不嚴格限制對象的類型,只要夠懶,遍地 any,就會把 TS 寫成 JS,因此爲了充分發揮 TS 的威力,必定要有良好的 TS 代碼風格。react-router

手勢滑動

爲了模仿 iOS 端能夠經過滑屏切換頁面的功能,經過監聽 touchStarttouchMovetouchEnd 來進行手勢的判斷並經過 transform 觸發模擬滾動實現,在 touchMove 中檢測監聽滑動的方向及距離,在 touchEnd 中觸發路由的切換及頁面吸附到整屏的位置。code

歌單的狀態保留

有這麼一個操做須要注意:用戶在某歌單往下滑了幾下,而後點了某歌播放而後進入了播放器,會發生路由的改變,若是此時從播放器返回,會丟包包括滾動位置在內的歌單頁的全部狀態丟失(由於 re-mount 了)。orm

我造了一個輪子來解決這個問題:react-live-route,是對 react-router-v4 中 Route 組件的加強,簡單的說就是將歌單頁隱藏掉而不是 unmount 掉,具體的解決思路能夠參考輪子裏的文檔。

跨組件傳遞狀態

在 iOS 版的網易雲中,能夠滑動來切換頁面,同時會觸發頂部 tab 下的滑塊移動。在項目中,滑動頁面與滑塊分屬於兩個兄弟組件的子組件且嵌套層次較深,若是直接經過 prop 來傳遞略顯醜陋,有以下解決方案:

  1. 經過 redux,可是 redux 最好只負責領域數據,這種 UI 的狀態就不要往 store 中放了。

  2. 經過 event-emitter,其實和 redux 差很少,由於 redux 也是基於 event-emitter 實現的, 可是不通過 react-redux 雖然能夠實現,可是破壞了 react 整個自頂向下界面更新的原則。

  3. 經過新的 context API 實現,以下圖:

API

項目中用到的網易雲音樂的 API 來自 NeteaseCloudMusicApi

TODO

目前還有一些部分沒完成,包括但不限於:

  • [ ] code splitting
  • [ ] 組件中有些功能仍是有耦合,須要再抽象
  • [ ] SSR

開發

克隆代碼到本地以後,須要在 4000 端口運行 NeteaseCloudMusicApi


項目地址:戳我

相關文章
相關標籤/搜索