基於 React 實現的仿 iOS 客戶端網易雲音樂。css
項目地址:戳我react
在線地址:戳我(PC 瀏覽器需切換到移動端模式)git
移動端體驗:github
目前只實現了上面四個頁面,可是整體的結構已經造成了,其餘頁面的添加只是時間上的問題 (實際上是懶),暫時沒有實現,下面是目前已實現的功能的細節:redux
像首頁的 banner 或者推薦歌單等,都是不會被共享的局部狀態,使用 Mobx 來進行請求的發起和狀態的管理。api
播放器的狀態是一個全局狀態,包括當前的播放列表,切歌,播放 / 暫停等,因此很天然的使用 redux 來進行管理,能夠清楚的掌握全部改變全局狀態的行爲。瀏覽器
儘管上手須要掌握一些語法,可是靜態類型與自動提示都能提供很大的幫助,在這個並不大的項目中我也體驗到了很大的幫助。可是要注意的是 TS 其實並不嚴格限制對象的類型,只要夠懶,遍地 any,就會把 TS 寫成 JS,因此爲了充分發揮 TS 的威力,必定要有良好的 TS 代碼風格。react-router
爲了模仿 iOS 端能夠經過滑屏切換頁面的功能,經過監聽 touchStart
,touchMove
,touchEnd
來進行手勢的判斷並經過 transform
觸發模擬滾動實現,在 touchMove
中檢測監聽滑動的方向及距離,在 touchEnd
中觸發路由的切換及頁面吸附到整屏的位置。code
有這麼一個操做須要注意:用戶在某歌單往下滑了幾下,而後點了某歌播放而後進入了播放器,會發生路由的改變,若是此時從播放器返回,會丟包包括滾動位置在內的歌單頁的全部狀態丟失(由於 re-mount 了)。orm
我造了一個輪子來解決這個問題:react-live-route,是對 react-router-v4 中 Route 組件的加強,簡單的說就是將歌單頁隱藏掉而不是 unmount 掉,具體的解決思路能夠參考輪子裏的文檔。
在 iOS 版的網易雲中,能夠滑動來切換頁面,同時會觸發頂部 tab 下的滑塊移動。在項目中,滑動頁面與滑塊分屬於兩個兄弟組件的子組件且嵌套層次較深,若是直接經過 prop 來傳遞略顯醜陋,有以下解決方案:
經過 redux,可是 redux 最好只負責領域數據,這種 UI 的狀態就不要往 store 中放了。
經過 event-emitter,其實和 redux 差很少,由於 redux 也是基於 event-emitter 實現的, 可是不通過 react-redux 雖然能夠實現,可是破壞了 react 整個自頂向下界面更新的原則。
經過新的 context API 實現,以下圖:
項目中用到的網易雲音樂的 API 來自 NeteaseCloudMusicApi。
目前還有一些部分沒完成,包括但不限於:
克隆代碼到本地以後,須要在 4000 端口運行 NeteaseCloudMusicApi。
項目地址:戳我