面試中問框架,常常會問到一些原理性的東西,明明一直在用,也知道怎麼用, 但面試時卻答不上來,也是挺尷尬的,就乾脆把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
shouldComponentUpdate
,這個方法用來判斷是否須要調用 render 方法重繪 dom。
由於 dom 的描繪很是消耗性能,若是咱們能在這個方法中可以寫出更優化的 dom diff 算法,能夠極大的提升性能。web
1.把樹形結構按照層級分解,只比較同級元素。 2.經過給列表結構的每一個單元添加的惟一 key值進行區分同層次的子節點的比較。 3.React 只會匹配相同 class 的 component(這裏面的 class 指的是組件的名字) 4.合併操做,調用 component 的 setState 方法的時候, React 將其標記爲 dirty. 到每個事件循環結束, React 檢查全部標記 dirty 的 component 從新繪製。 5.選擇性渲染。開發人員能夠重寫 shouldComponentUpdate 提升 diff 的性能。
圖片源自:react精髓之一---diff算法面試
實現原理:算法
1. 用 js對象結構表示 DOM 樹的結構;而後用這個樹構建一個真正的 DOM 樹,插到文檔當中。 2. 當狀態變動的時候,從新構造一棵新的對象樹。而後對比新舊虛擬DOM樹,記錄兩棵樹差別。 3. 把 2 所記錄的差別應用到步驟 1 所構建的真正的 DOM 樹上,視圖就更新了。 緣由:虛擬 dom 至關於在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法減小了對真實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
state 是一種數據結構
,用於組件掛載時所需數據的默認值。state 可能會隨着時間的推移而發生突變,但多數時候是做爲用戶事件行爲的結果。
Props則是組件的配置
。props 由父組件傳遞給子組件,而且就子組件而言,props 是不可變的(immutable)
。
父子:父傳子:props; 子傳父:子調用父組件中的函數並傳參;
兄弟:利用redux實現。
全部關係都通用的方法:利用PubSub.js
訂閱
原理:當調用setState時,它並不會當即改變,而是會把要修改的狀態放入一個任務隊列,等到事件循環結束時,再合併指更新。
所以,setState有 異步,合併更新
更新兩個特性。
這裏應該須要瞭解下 Batch Update 。
使用:
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 })
參考連接: React 中 setState() 爲何是異步的?、 react的setstate原理
1.保證內部的一致性
由於props是要等到父組件渲染事後才能拿到,也就是不能同步更新,state出於統一性設成異步更新。
2.性能優化
舉例說你正在一個聊天窗口輸入,若是來了一條新消息又要render,那就會阻塞你的當前操做,致使延遲什麼的。
3.支持state在幕後渲染
異步可使state在幕後更新,而不影響你當前舊的頁面的交互,提高用戶體驗。
詳情能夠點擊上面的參考連接,寫的很詳細的。
另外:setstate在原生事件,setTimeout,setInterval,promise等異步操做
中,state會同步更新
。
優點:
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能夠與已知的庫或框架很好地配合。
講一些項目中用到的小的點:
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
有些是我的意見,僅供參考。
相同點:
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,固然這也不是絕對。
用戶頁面行爲觸發一個Action
,而後,Store
自動調用 Reducer
,而且傳入兩個參數:當前 State 和收到的 Action。Reducer 會返回新的 State 。每當state更新以後,view
會根據state觸發從新渲染。
Redux做爲一個通用模塊,主要仍是用來處理應用中state的變動,經過react-redux作鏈接,能夠在React+Redux的項目中將二者結合的更好。
react-redux是一個輕量級的封裝庫,它主要經過兩個核心方法實現:
Provider:從最外部封裝了整個應用,並向connect模塊傳遞store。 Connect: 一、包裝原組件,將state和action經過props的方式傳入到原組件內部。 二、監聽store tree變化,使其包裝的原組件能夠響應state變化
理解:中間件就是要對redux的store.dispatch方法作一些改造,以實現其餘的功能。
我用過redux-thunk
,就拿它舉例。
背景:Redux 的基本作法,是用戶發出 Action,Reducer 函數馬上算出新的 State,View 從新渲染,但這是作同步。 而若是有異步請求時,那就不能知道何時獲取的數據有存進store裏面,所以此時須要在請求成功時返回一個標識或狀態,並在此時再觸發action給reducer傳值。 所以,爲了解決異步的問題,就引入了中間件的概念。
做用: redux-thunk 幫助你統一了異步和同步 action 的調用方式,把異步過程放在 action 級別解決,對 component 調用沒有影響。
引入使用可參照: 理解redux和redux的中間件redux-thunk的認識
原文連接: 異步方案選型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) 異步操做的流程是能夠控制的,能夠隨時取消相應的異步操做。
缺點:學習成本高。
原文連接不記得了(囧...)
相同點:
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
原理:實現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不太穩定,在升級版本的時候須要進行代碼變更。
我只挑了一部分。
原文連接: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是一個預編譯模塊方案,它會分析你的項目結構將其打包成適合瀏覽器加載的模塊。
打包原理:把全部依賴打包成一個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高階組件
定義: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'
高階組件部分還有待補充。