React專題:react,redux以及react-redux常見一些面試題

面試中問框架,常常會問到一些原理性的東西,明明一直在用,也知道怎麼用,
但面試時卻答不上來,也是挺尷尬的,就乾脆把react相關的問題查了下資料,再按本身的理解整理了下這些答案。

react生命週期有哪些

組件載入階段:
componentWillMount:組件即將被裝載、渲染到頁面上,只調用1次
componentDidMount:組件真正在被裝載以後,這裏能夠拿到真實DOM執行操做,只調用1次css

運行中狀態:
componentWillReceiveProps(nextProps):組件將要接收到新屬性的時候調用,在這時setState不會觸發額外的render,由於此時已經有一次來自父組件引起的render了。html

shouldComponentUpdate:組件接受到新屬性或者新狀態的時候(返回 false,接收數據後不更新,阻止 render ,後面的函數不會繼續執行)
componentWillUpdate:組件即將更新不能修改屬性和狀態
componentDidUpdate:組件已經更新vue

銷燬階段:
componentWillUnmount:組件即將銷燬,這時候能夠銷燬綁定的事件監聽或者定時器什麼的。react

有些好像把render也算進生命週期了:
render:組件在這裏生成虛擬的 DOM 節點webpack

react在哪一個生命週期作優化

shouldComponentUpdate,這個方法用來判斷是否須要調用 render 方法重繪 dom。
由於 dom 的描繪很是消耗性能,若是咱們能在這個方法中可以寫出更優化的 dom diff 算法,能夠極大的提升性能。web

react的diff算法是怎麼完成的

1.把樹形結構按照層級分解,只比較同級元素。
2.經過給列表結構的每一個單元添加的惟一 key值進行區分同層次的子節點的比較。
3.React 只會匹配相同 class 的 component(這裏面的 class 指的是組件的名字)
4.合併操做,調用 component 的 setState 方法的時候, React 將其標記爲 dirty.
    到每個事件循環結束, React 檢查全部標記 dirty 的 component 從新繪製。
5.選擇性渲染。開發人員能夠重寫 shouldComponentUpdate 提升 diff 的性能。

clipboard.png
圖片源自:react精髓之一---diff算法面試

react虛擬DOM實現原理,以及爲何虛擬 dom 會提升性能

實現原理:算法

1. 用 js對象結構表示 DOM 樹的結構;而後用這個樹構建一個真正的 DOM 樹,插到文檔當中。
2. 當狀態變動的時候,從新構造一棵新的對象樹。而後對比新舊虛擬DOM樹,記錄兩棵樹差別。
3. 把 2 所記錄的差別應用到步驟 1 所構建的真正的 DOM 樹上,視圖就更新了。

緣由:虛擬 dom 至關於在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法減小了對真實DOM的操做次數,從而提升性能。

react怎麼從虛擬dom中拿出真實dom

Refs 是 React 提供給咱們的安全訪問 DOM 元素或者某個組件實例的句柄。
咱們能夠爲元素添加 ref 屬性而後在回調函數中接受該元素在 DOM 樹中的句柄,該值會做爲回調函數的第一個參數返回。或者ref能夠傳字符串。vuex

例如:<input ref=((input)=>{return this.name=input}) />, this.name.value取值
或者 <input ref="name" />,this.refs.name取值json

React中的props和state的用法

state 是一種數據結構,用於組件掛載時所需數據的默認值。state 可能會隨着時間的推移而發生突變,但多數時候是做爲用戶事件行爲的結果。
Props則是組件的配置。props 由父組件傳遞給子組件,而且就子組件而言,props 是不可變的(immutable)

react組件之間如何通訊

父子:父傳子:props; 子傳父:子調用父組件中的函數並傳參;
兄弟:利用redux實現。
全部關係都通用的方法:利用PubSub.js訂閱

react的setState的原理及用法

原理:當調用setState時,它並不會當即改變,而是會把要修改的狀態放入一個任務隊列,等到事件循環結束時,再合併指更新。
所以,setState有 異步,合併更新更新兩個特性。

這裏應該須要瞭解下 Batch Update

clipboard.png

使用:
1.最多見的用法就是傳入一個對象。

this.setState({
        isLoading:false
    })

2.還能夠接收一個函數

this.setState((prevState,props)=>{
        // 要作的事件
        return {isLoading:false};
    })

3.由於setState是異步的,因此它還能夠接收第二個參數,一個回調函數

this.setState({count:2},()=>{
        isLoading:this.state.count===2 ? true : false
    })

setState爲何是異步的

參考連接: React 中 setState() 爲何是異步的?react的setstate原理

1.保證內部的一致性

由於props是要等到父組件渲染事後才能拿到,也就是不能同步更新,state出於統一性設成異步更新。

2.性能優化

舉例說你正在一個聊天窗口輸入,若是來了一條新消息又要render,那就會阻塞你的當前操做,致使延遲什麼的。

3.支持state在幕後渲染

異步可使state在幕後更新,而不影響你當前舊的頁面的交互,提高用戶體驗。

詳情能夠點擊上面的參考連接,寫的很詳細的。

另外:setstate在原生事件,setTimeout,setInterval,promise等異步操做中,state會同步更新

react的優點以及特色

優點:

1. 實現對虛擬DOM的操做,使得它速度快,提升了Web性能。
2. 組件化,模塊化。react裏每個模塊都是一個組件,組件化開發,可維護性高。
3. 單向數據流,比較有序,有便於管理,它隨着React視圖庫的開發而被Facebook概念化。
4. 跨瀏覽器兼容:虛擬DOM幫助咱們解決了跨瀏覽器問題,它爲咱們提供了標準化的API,甚至在IE8中都是沒問題的。

不足:

1. react中只是MVC模式的View部分,要依賴引入不少其餘模塊開發。、
2. 當父組件進行從新渲染操做時,即便子組件的props或state沒有作出任何改變,也會一樣進行從新渲染。

特色: 

1. 聲明式設計:React採用聲明範式,能夠輕鬆描述應用。
2. 高效:React經過對DOM的模擬,最大限度地減小與DOM的交互。
3. 靈活:React能夠與已知的庫或框架很好地配合。

React如何性能優化

講一些項目中用到的小的點:

1. 充分利用shouldComponentUpdate函數,不過這須要你的組件儘可能最小化,若是當前組件數據過於複雜,實際上是很難優化的。
2. 給你的DOM遍歷上加上惟一的key,注意儘可能不要用index,由於若是你新DOM中刪了某一個節點,它會從新排列index,
那跟原來同層級一比就都會徹底不同,而從新渲染了,因此最好使用id值什麼的做key值。

3. 能用const聲明的就用const。
4. DOM裏少用箭頭函數,固然其實要傳參時也仍是得用。再者,函數bind儘可能寫在constructor,避免每次render從新bind。
5. 減小對真實DOM的操做。
6. 若是是用webpack搭建環境的話,當一個包過大加載過慢時,可分打成多個包來優化。
react-perf性能查看工具,可自行了解下: react-perf

react與vue的對比

有些是我的意見,僅供參考。

相同點:

1. 都用虛擬DOM實現快速渲染
2. 我以爲父子,兄弟通訊這些都挺像的,也都有本身的狀態管理器:react=>redux, vue=>vuex
3. 都是輕量級框架
4. 如今vue也在漸漸吸取react中的一些語法,好比JSX語法,類式聲明寫法等

不一樣點:

1. React屬於單向數據流——MVC模式,vue則屬於雙向——MVVM模式。
2. react兼容性比vue好,vue不兼容IE8.
3. react採用JSX語法,vue採用的則是html模板語法。
4. vue的css能夠有組件的私有做用域,react則沒有。
5. react比vue好的另外一點是,它是團隊維護,而vue屬於我的,通常來講,大型項目更傾向於react,小型則用vue,固然這也不是絕對。

Redux的實現流程

用戶頁面行爲觸發一個Action,而後,Store 自動調用 Reducer,而且傳入兩個參數:當前 State 和收到的 Action。Reducer 會返回新的 State 。每當state更新以後,view會根據state觸發從新渲染。

react-redux的實現原理

Redux做爲一個通用模塊,主要仍是用來處理應用中state的變動,經過react-redux作鏈接,能夠在React+Redux的項目中將二者結合的更好。
react-redux是一個輕量級的封裝庫,它主要經過兩個核心方法實現:

Provider:從最外部封裝了整個應用,並向connect模塊傳遞store。
Connect: 
    一、包裝原組件,將state和action經過props的方式傳入到原組件內部。
    二、監聽store tree變化,使其包裝的原組件能夠響應state變化

redux中間件的理解,以及用過哪些中間件

理解:中間件就是要對redux的store.dispatch方法作一些改造,以實現其餘的功能。

我用過redux-thunk,就拿它舉例。

背景:Redux 的基本作法,是用戶發出 Action,Reducer 函數馬上算出新的 State,View 從新渲染,但這是作同步。

而若是有異步請求時,那就不能知道何時獲取的數據有存進store裏面,所以此時須要在請求成功時返回一個標識或狀態,並在此時再觸發action給reducer傳值。
所以,爲了解決異步的問題,就引入了中間件的概念。

做用: redux-thunk 幫助你統一了異步和同步 action 的調用方式,把異步過程放在 action 級別解決,對 component 調用沒有影響。

引入使用可參照: 理解redux和redux的中間件redux-thunk的認識

redux-thunk VS redux-saga對比 異步處理方案中間件

原文連接: 異步方案選型redux-saga 和 redux-thunk

redux-thunk
缺點:

(1).一個異步請求的action代碼過於複雜,且異步操做太分散,相對比saga只要調用一個call方法就顯得簡單多了。
(2).action形式不統一,若是不同的異步操做,就要寫多個了。

優勢:學習成本低

redux-saga:
優勢:

(1)集中處理了全部的異步操做,異步接口部分一目瞭然(有提供本身的方法)
(2)action是普通對象,這跟redux同步的action如出一轍({type:XXX})
(3)經過Effect,方便異步接口的測試
(4)經過worker和watcher能夠實現非阻塞異步調用,而且同時能夠實現非阻塞調用下的事件監聽
(5) 異步操做的流程是能夠控制的,能夠隨時取消相應的異步操做。

缺點:學習成本高。

比較redux和vuex的區別

原文連接不記得了(囧...)
相同點:

1.數據驅動視圖,提供響應式的視圖組件
2.都有virtual DOM, 組件化開發,經過props參數進行父子組件數據的傳遞,都實現webComponents規範
3.都支持服務端渲染  
4.都有native解決方案,reactnative(facebook團隊) vs weex(阿里團隊)

不一樣點:

1.vuex是一個針對VUE優化的狀態管理系統,而redux僅是一個常規的狀態管理系統(Redux)與React框架的結合版本。
2.開發模式:React自己,是嚴格的view層,MVC模式;Vue則是MVVM模式的一種方式實現
3.數據綁定:Vue借鑑了angular,採起雙向數據綁定的方式;React,則採起單向數據流的方式
4.數據更新:Vue採起依賴追蹤,默認是優化狀態:按需更新;
    React在則有兩種選擇:
    1)手動添加shouldComponentUpdate,來避免冗餘的vdom,re-render的狀況
    2)Components 儘量都用 pureRenderMixin,而後採用 redux 結構 + Immutable.js
5.社區:react相比來說仍是要大於vue,畢竟背後支撐團隊不一樣。
    facebook vs 我的!固然目前vue的增加速度是高於react的增速,不知道將來的發展趨勢是如何。

總之:期待構建一個大型應用程序——選擇React,期待應用盡量的小和快——選擇Vue

react-router的實現原理

原理:實現URL與UI界面的同步。其中在react-router中,URL對應Location對象,
而UI是由react components來決定的,這樣就轉變成location與components之間的同步問題。

優勢:

1.風格: 與React融爲一體,專爲react量身打造,編碼風格與react保持一致,例如路由的配置能夠經過component來實現
2.簡單: 不須要手工維護路由state,使代碼變得簡單
3.強大: 強大的路由管理機制,體如今以下方面
4.路由配置: 能夠經過組件、配置對象來進行路由的配置
5.路由切換: 能夠經過<Link> Redirect進行路由的切換
6.路由加載: 能夠同步記載,也能夠異步加載,這樣就能夠實現按需加載
7.使用方式: 不只能夠在瀏覽器端的使用,並且能夠在服務器端的使用

缺點:API不太穩定,在升級版本的時候須要進行代碼變更。

react router3到4有什麼改變

我只挑了一部分。
原文連接:https://blog.csdn.net/qq_3548...

1. V4再也不使用V3裏的{props.children}(表明全部路由-我的理解),而V4丟給 DOM 的是咱們的應用程序自己.
2. V4還同時支持同時渲染多個路由,1和2均可參照下面代碼,當訪問 /user 時,兩個組件都會被渲染。(V3可實現但過程複雜)
<div className="primary-layout">
    <header>
      Our React Router 4 App
      <Route path="/user" component={UsersMenu} />
    </header>
    <main>
      <Route path="/" exact component={HomePage} />
      <Route path="/user" component={UsersPage} />
    </main>
  </div>;
3.獲取路由的路徑匹配,可使用props.match.path獲取,match上還有match.params,match.url等屬性。
注:url是瀏覽器的url的一部分,path是給router寫的路徑
4.多了一個限制未登陸的用戶訪問某些路由功能,能夠在應用程序頂端中設置一個主入口,區別登陸和未登陸UI展現界面。

對webpack的理解:

參考連接: webpack配置整理

概念: webpack是一個預編譯模塊方案,它會分析你的項目結構將其打包成適合瀏覽器加載的模塊。
打包原理:把全部依賴打包成一個bundle.js文件,經過代碼分割成單元片斷並按需加載。
核心思想:

1.一切皆模塊,一個js,或者一個css文件也都當作一個模塊,
2.按需加載,傳統的模塊打包工具(module bundlers)最終將全部的模塊編譯生成一個龐大的bundle.js文件。
    可是在真實的app裏邊,「bundle.js」文件可能有10M到15M之大可能會致使應用一直處於加載中狀態。
    所以Webpack使用許多特性來分割代碼而後生成多個「bundle」文件,並且異步加載部分代碼以實現按需加載。

基礎配置項:

1. entry:{} 入口,支持多入口
2. output 出口
3. resolve 處理依賴模塊路徑的解析
4. module 處理多種文件格式的loader
5. plugins 除了文件格式轉化由loader來處理,其餘大多數由plugin來處理
6. devServer 配置 webpack-dev-server
7. 搭配package.json配置環境變量,以及腳本配置。
"scripts": {
    "build": "webpack --mode production",
    "start": "webpack-dev-server --mode development"
}

"scripts": {
    "build_": "NODE_ENV=production webpack",
    "start_": "NODE_ENV=development webpack-dev-server"
}

react高階組件

參考資料: 淺談React高階組件
通俗理解 React 高階函數
深刻淺出React高階組件
定義:js裏的高階函數的定義是接收一個函數做爲參數,並返回一個函數。redux的connect就是一個高階函數。
那react高階組件就是指接收一個react組件做爲入參,並返回一個新react組件的組件。

好處:它不用關心組件從哪來,也就是不用本身去引入不少個組件了。
一個簡單的高階組件:(寫法不是惟一)

export default function withHeader(WrappedComponent){
        return class HOC extends component{
            return (
                <div className="wrap">
                    <div>這是一段普通的文字</div>
                    <WrappedComponent {...this.props} />
                </div>
            )
        }
    }

直接引入:import withHeader from 'withHeader'

高階組件部分還有待補充。

相關文章
相關標籤/搜索