1、React是什么
React是一個為數據提供渲染為HTML視圖的開源JavaScript庫。擁有虛擬DOM、組件化設計模式、聲明式代碼、單向數據流、使用JSX描述UI信息等特點。
2、 Real DOM和Virtual DOM
React不直接操作DOM,而是實現了Virtual DOM,組件DOM結構映射到這個虛擬DOM上。React在虛擬DOM上實現了diff算法,當要重新渲染組件的時候,會通過diff尋找到要變更的DOM節點,再把這個修改更新到瀏覽器實際上的DOM節點。
虛擬DOM相當於在JS和真實DOM中間加了一個緩存,利用diff減少了沒有必要的操作,從而提高了性能,本質上是JS對象。
3、React中keys和diff算法
keys是React用於追蹤元素被修改、添加或移除的輔助標識。我們需要保證元素的key在列表中具有唯一性,這樣可以幫助React定位到正確的節點進行比較,從而大幅減少DOM操作的次數,提高性能。
diff算法的作用是用來計算出Virtual DOM中被改變的部分,然后針對該部分進行原生DOM的操作,而不用重新渲染整個頁面。
diff算法有三種策略:
- tree diff:DOM節點跨層級的移動操作特別少,可以忽略不計。
- component diff:擁有相同類的兩個組件生成相似的數據結構;擁有不同類的兩個組件生成不同的樹形結構。
- element diff:對於同一層級的一組子節點,通過唯一id區分。
diff算法原理:
- 將樹形結構按照層級分解,只比較同級元素。
- 給列表結構的每個單元添加唯一的key屬性,方便比較。
- React只會匹配相同class的component
- 合並操作,調用component的setState方法的時候,React將其標記為dirty,到每一輪事件循環結束,React檢查所有標記dirty的component重新渲染。
- 選擇性子樹渲染。開發人員可以重新shouldComponentUpdate提高diff的性能。
4、React中的Element與Component
ReactElement是描述屏幕上可見內容的數據結構,是對於UI對象的表述。
ReactComponent則是可以接受參數輸入並且返回某個ReactElement的函數或者類。
5、JSX是什么
JSX是JavaScript XML的縮寫,是一個JavaScript的語法擴展,本質上是JavaScript對象。JSX可以很好的描述UI信息,但是瀏覽器無法直接讀取,編譯的過程中會將JSX轉換成JavaScript的對象結構。
6、ES5、ES6、ES7、ES8對比
ES5:擴展了Object、Array、Function等功能
ES6:類、模塊化、箭頭函數、塊級作用域、賦值解構、擴展運算符、Promise、新數據結構Set,Map,Symbol、字符串模板等
ES7:指數操作符、Array.prototype.includes()等
ES8:異步函數使用形式、異步編程機制Generator和async/await、Object.entries()、Object.values()、Object.getOwnPropertyDescriptors()等
7、props和state
props是React中屬性的簡寫,是不可變的,可以從父組件傳入參數配置該組件。
state是用於組件保存、控制、修改自己的可變狀態。
沒有設置state的組件叫無狀態組件,設置了state的組件叫有狀態組件。有狀態組件通過繼承component來構建,一個子類就是一個組件;無狀態組件通過函數式聲明來構建,一個函數就是一個組件。
8、通信
React中的組件通信有以下幾種情況:
- 父子組件通信
- 兄弟組件通信
- 跨多層次組件通信
- 任意組件通信
父子組件通信:父組件通過props傳遞參數給子組件,子組件通過調用父組件傳來的函數傳遞數據給父組件。
兄弟組件通信:通過使用共同的父組件來管理狀態和事件函數。一個組件通過父組件傳來的函數修改父組件的狀態,父組件再將狀態傳遞給另一個子組件。
跨多層次組件通信:使用Context API。
任意組件:使用Redux或者Event Bus。
9、生命周期函數
getDefaultProps:獲取實例的默認屬性。
getInitialState:獲取每個實例的初始化狀態。
componentWillMount:組件即將被裝載、渲染到頁面上。
componentDidMount:組件已經被裝載到頁面上。
componentWillReceiveProps:組件將要接收到屬性的時候調用。
shouldComponentUpdate:組件接收到新屬性或者新狀態的時候。
componentWillUpdate:組件即將更新。
componentDidUpdate:組件已經更新。
componentWillUnmount:組件卸載。
10、React中的refs
refs是React提供給我們的安全訪問DOM元素或者某個組件實例的句柄。我們可以為添加ref屬性然后在回調函數中接受該元素在DOM樹中的句柄,該值會作為回調函數的第一個參數返回:
class CustomForm exrends Component {
handleSubmit = () => {
console.log("Input Value:", this.input.value)
}
render() {
return(
<form onSubmit={this.handleSubmit}>
<input type='text' ref={input => this.input = input} />
<button type='submit'>Submit</button>
</form>
)
}
}
代碼中的input包含了一個ref屬性,該屬性聲明的回調函數會接收input對應的DOM元素,我們將其綁定到this指針以便在其他類函數中使用。另外ref在函數式組件同樣能夠利用閉包暫存其值。
11、受控組件
<input>
,<textarea>
和<select>
這樣的表單會維護自己的狀態,基於用戶的輸入來更新。而在React中,可變狀態通常保存在組件的state屬性中,並且只能通過使用setState()
來更新。這樣的組件就叫做受控組件。
12、高階組件
高階組件就是一個以組件作為參數,並返回一個組件的函數。高階組件的作用就為了提高組件之間的代碼復用。如果組件有某些相同的邏輯,那我們可以將這些邏輯抽離出來,放到高階組件中進行復用,高階組件和參數組件使用props傳遞數據。
13、Flux和Redux
Flux是一種強制單向數據流的架構模式。
Flux主要有這幾個部分:
- Dispatcher調度:處理動作分發,維護store之間的依賴關系;
- Stores存儲:數據和邏輯部分;
- Views:React組件,作為視圖同時響應用戶交互;
- Actions提供給dispatcher傳遞數據給store。
Flux工作流程:
1、用戶訪問View;
2、View發送出用戶的Action;
3、Dispatcher收到Action,要求Store進行響應的更新;
4、Store更新后,發出change事件;
5、View收到change事件后,更新頁面。
Redux是JavaScript狀態容器,提供可預測化的狀態管理。
Redux有三大原則:單一數據來源、State是只讀的、使用純函數進行更改。
Redux原理是集中式管理,主要有三個核心方法:action、store、reducer。
Redux工作流程:
1、應用調用store的dispatch接受action傳入store;
2、reducer進行state操作;
3、應用通過store提供的getState獲取最新的數據。
Flux和Redux主要區別在於Flux有多個可以改變應用狀態的store,在Flux中dispatcher被用來傳遞數據到注冊的回調事件;在Redux中只能定義一個可更新狀態的store,redux把store和Dispatcher合並,結構更加簡單清晰。
Redux的缺點:
- 一個組件所需要的數據,必須由父組件傳過來,而不能向Flux一樣直接從store獲取。
- 當一個組件數據更新時,即使父組件不需要用到這個組件,夫組件還是會重新render。
14、React-Router
React-Router是一個基於React之上的強大路由庫,它可以讓你向應用中快速地添加視圖和數據流,同時保持頁面與URL間的同步。
Router用於定義多個路由,當用戶定義特定的URL時,如果此URL與Router內定義的任何“路由”的路徑匹配,則用戶將重定向到該特定路由。