使用React和Node.js製作網易雲音樂App的一次總結 【實現全部基本核心功能】

Jeery_譚金傑發表於2019-04-08

一、技術選型

  • 語言選擇:

    • JavaScript
    • TypeScript
    • 最終選擇了JavaScript作為開發語言,一開始嘗試使用TypeScript,但是由於是移動端,antd-mobile的庫與TS有那麼一些不相容,官方文件上也沒有像PC端那樣推薦你使用TS,踩過坑,於是換回了JS
  • 開發環境 create-react-app 目前最好用的開發React環境

  • UI元件庫的選擇:

    • Swiper.js 個人認為Swiper在對Vue的支援會更好,官方文件上也沒有明確支援React
    • antd-mobile阿里旗下的庫,PC端的功能強大,但是更多使用場景是 TO-B ,這裡只做嘗試使用,個人覺得TO-C專案不建議使用,本專案中也僅僅使用到了一點點這個元件庫的功能
    • 圖示庫,Echarts Bizcharts G2 選擇了 Bizcharts ,因為它對React元件化支援更好。
  • 介面呼叫,網易雲音樂的原生介面,Music和Mv都使用它的原生介面

  • 開發所需的包

  • pubsub-jsstate的管理的包

  • react-router-dom路由

  • antd-mobile官方推薦的按需載入配置

  • less-loader對less的支援

  • Node.js端

  • express框架(有考慮KOA2框架,但是鑑於express的成熟性沒有選擇)

  • puppeteer爬蟲獲取資料的包

  • ws模組,webSocket的使用

  • request-promise-native,使用Node.js的伺服器無跨域特性傳送請求呼叫網易雲音樂介面

  • 版本控制工具,毫無疑問使用Git

  • 包管理器,這裡使用的是yarn,不是npm

技術選型對於後期迭代非常重要,個人建議大專案上TSReact

二、專案所需要到的知識點

由於是在移動端,H5 , C3 , 事件處理還有效能優化考慮的問題要更多

  • 基礎知識點
    • 主打音樂類APP,需要使用到的H5標籤,<audio> <video>
    • C3技術,canvas,Animation等製作一些動畫
    • 對移動端的一些特殊情況,比如圓角過圓等的處理。
    • JSX語法,比較基本的JSX語法一定是要非常熟練的
    • ES5/6 TypeScript,為什麼需要TS的知識? 為了看懂原始碼,更好除錯程式碼。
  • React知識點
    • React的事件機制,原生事件和合成事件的觸發哪個優先順序更高,事件代理,事件派發是什麼過程?
    • setState的非同步同步問題,其實就是上面的事件機制,這個問題遇到的還是非常多的,如果搞不懂,那麼除錯起來非常困難
    • React中追求元件化,個人喜歡元件化到極致,這樣方便除錯,在使用TSReact配合時,除錯真的非常簡單
    • prop-types限制傳入的props的型別(隱約有TS的影子)
    • 高階函式的使用 React中對於大量的重複邏輯函式,使用函式柯里化給予預設引數和封裝成高階函式使用
    • 高階元件也是用得非常多,對於一些重複邏輯的元件,我們可以封裝成高階元件,即傳入值是一個元件,返回的是一個新的元件。
    • React V16版本的Fiber架構,跟之前的區別? 新版本的執行render()時候,是分割成多個小任務,可取消中斷的過程,配合原生JSrequestAnimationFrame(高優先順序別的任務處理)和requestIdleCallback(低優先順序別的任務處理),達到效能優化的目的。
    • Reactdiff演算法,三種diff模式:
      • Tree diff是優先對比兩棵樹的同級別DOM節點,所以儘量不要將DOM節點徹底刪除,否則會讓Reactrender()時間變長,具體在操作樣式時候這點會非常明顯,需要將一個元素隱藏時候如果display:none,如果切換顯示和隱藏特別頻繁,那麼會出現閃屏。
      • Component diff是對元件的diff,其實我們可以通過shouldComponentUpdate的生命週期函式返回值控制元件是否重新渲染,它的兩個引數是(nextProps,subState),返回值是ture則重新渲染元件,反之NO
      • element diff,為什麼在React中需要元素要有一個唯一的key值,因為底層的diff演算法是四根指標,例如遍歷兩個元素 old element: A,C,B,Dnew element B,C,A,D 。 如果沒有唯一的key值,那麼diff演算法生成新的虛擬DOM節點過程是:發現第一個不一樣,那麼直接插入B,C,A,D ; 但是如果有唯一的key值,那麼React的diff演算法會發現,裡面有一樣的元素,那麼:插入B,C不動,插入A,D不動。 所以唯一的key值多重要?

三、移動端的不一樣

  • 滑動時頁面警告
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive.
解決方法

* {
    -ms-touch-action: pan-y;
    touch-action: pan-y;
}
複製程式碼
  • 事件點選穿透,禁止一個事件的預設行為,對其手指抬起事件繫結邏輯。

  • antd-mobile的按需載入需要配置更多,圖示和功能也更少。

  • touches targettouches changedtouches的區別,處理一些複雜邏輯會用到

  • 在對製作SPA單頁面應用時,頻繁切換的一些元素,做效能優化處理,利用上面提到的那些React知識點,不然很可能出現閃屏,使用者體驗感差。

  • http通訊時,如果要將返回的資料setState,那麼請注意setState的同非同步場景,準確把控渲染和設定狀態時間差邏輯,特別是多個請求,可以使用`promise.all 或者在setState的回撥函式中傳送請求,定時器把控時間。

比如下面這段程式碼,需要傳送10個請求並且將返回的資料整合,再把陣列中的10個promise物件的值取出,設定成狀態重新渲染。

`首先在生命週期函式componentDidMount中  this.createSrc() 呼叫`
 reqMvList=() => {
        const {data, src}=this.state;
        const MvList=data.map(async item => {
            const result=await reqMv(item.id)
            const {data: {brs}}=result;
            return brs[480]
        })
        return MvList
    }
    `呼叫createSrc函式後會先呼叫reqMvList函式,拿到結果`
    createSrc=() => {
        const result=this.reqMvList()
        let arr=[]
        result.forEach(item => {
            item.then(res => {
                arr=[res, ...arr]
                return res
            })
        })
        `上面將得到的10個promise物件中的值全部取出放到陣列中`
        setTimeout(() => {
            this.setState({
                src:arr
            })
        }, 1000);
    }
        `如果此時不加定時器,那麼會先執行setState的程式碼,再去執行promise.then裡面的邏輯,
        那麼其實狀態已經更新完了,但是資料是後面新增到arr中的,所以會出現狀態裡面沒有值的情況,
        這裡需要加一個定時器解決。`
    ```
    



### 本次構建過程中涉及到的一些面試題

* `http的ajax輪詢 長輪詢 keep-alive 和webSocket的區別`

* `如何將一個元素從頁面上隱藏 根據場景需求,配合React的Fiber和diff演算法機制使用`
* `高階函式,高階元件,函式柯里化的使用`
* `如何在一個請求回來資料並且在設定狀態成功後傳送下面的請求(優雅傳送請求,平鋪資料)?`
* `手寫一個promise`
* `promise.all`的使用
* `pubsub-js`的使用
* `React`的三大屬性
* 對於高階元件中的修飾器的使用,例如`@withRouter ` 
* `cookie和cors`如何配合使用? `cookie`可以跨域嗎?
* `requestAnimationFrame`和`requestIdleCallback`的區別,在`React的Fiber中`
* `Node.js端`對`request-promise-native`的使用
* 現在的效能優化真的只看 `DOMContentLoad和Load的時間嗎?` 可以從`RASI`四個方面去看待。


> 由於太晚了,面試題的答案會放出來。喜歡的朋友請收藏,謝謝。 感謝@xpromise的技術支援





複製程式碼

相關文章