1.當你調用 setState 的時候,發(fā)生了什么事?
將傳遞給 setState 的對象合并到組件的當前狀態(tài),
這將啟動一個和解的過程,構建一個新的 react 元素樹,
與上一個元素樹進行對比(diff),從而進行最小化的重渲染。
2. .React 項目用過什么腳手架(開放性題目)
答:creat-react-app Yeoman 等
解析:原理回答用webpack loader Plugin插件可以實現
3.什么時候用類組件Class Component,或函數組件Function
答:如果您的組件具有狀態(tài)(state)或生命周期方法,請使用Class組件。否則,使用功能組件;
4.React 中 keys 的作用是什么?
答:Keys 是 React 用于追蹤哪些列表中元素被修改、被添加或者被移除的輔助標識。
render () {
return (
<ul>
{this.state.todoItems.map(({item, key}) =>{
return <li key={key}> {item} </li>
})}
</ul>
)
}
在開發(fā)過程中,我們需要保證某個元素的 key 在其同級元素中具有唯一性。在 React Diff 算法中 React 會借助元素的 Key 值來判斷該元素是新近創(chuàng)建的還是被移動而來的元素,從而減少不必要的元素重渲染。此外,React 還需要借助 Key 值來判斷元素與本地狀態(tài)的關聯關系,因此我們絕不可忽視轉換函數中 Key 的重要性。
5.React 優(yōu)勢
答:
- 1、React 速度很快:它并不直接對 DOM 進行操作,引入了一個叫做虛
DOM 的概念,安插在 javascript 邏輯和實際的 DOM 之間,性能好。 - 2、跨瀏覽器兼容:虛擬 DOM 幫助我們解決了跨瀏覽器問題,它為我們
提供了標準化的 API,甚至在 IE8 中都是沒問題的。 - 3、一切都是 component:代碼更加模塊化,重用代碼更容易,可維護性高。
- 4、單向數據流:Flux 是一個用于在 JavaScript 應用中創(chuàng)建單向數據層的架構, 它隨著 React 視圖庫的開發(fā)而被 Facebook 概念化。
- 5、同構、純粹的 javascript:因為搜索引擎的爬蟲程序依賴的是服務端響
應而不 是 JavaScript 的執(zhí)行,預渲染你的應用有助于搜索引擎優(yōu)化。 - 6、兼容性好:比如使用 RequireJS 來加載和打包,而 Browserify 和 Webpack 適用于構建大型應用。它們使得那些艱難的任務不再讓人望而生畏。
6.react diff 原理(??迹?/h4>
答:把樹形結構按照層級分解,只比較同級元素。
給列表結構的每個單元添加唯一的 key 屬性,方便比較。
React 只會匹配相同 class 的 component(這里面的 class 指的是組件的名字) 合并操作,調用 component 的 setState 方法的時候, React 將其標記為 dirty.
到每一個事件循環(huán)結束, React 檢查所有標記 dirty 的 component 重新繪制. 選擇性子樹渲染。開發(fā)人員可以重寫 shouldComponentUpdate 提高 diff 的性能。
7.react 生命周期函數
答:
1.初始化階段:
- getDefaultProps:獲取實例的默認屬性
- getInitialState:獲取每個實例的初始化狀態(tài)
- componentWillMount:組件即將被裝載、渲染到頁面上
- render:組件在這里生成虛擬的 DOM 節(jié)點
- componentDidMount:組件真正在被裝載之后
- 運行中狀態(tài):
- componentWillReceiveProps:組件將要接收到屬性的時候調用
- shouldComponentUpdate:組件接受到新屬性或者新狀態(tài)的時候(可以返回 false,接收數據后不更新,阻止 render 調用,后面的函數不會被繼續(xù)執(zhí)行了)
- componentWillUpdate:組件即將更新不能修改屬性和狀態(tài)
- render:組件重新描繪
- componentDidUpdate:組件已經更新
3.銷毀階段: - componentWillUnmount:組件即將銷毀
8. shouldComponentUpdate 是做什么的?
答:shouldComponentUpdate 這個方法用來判斷是否需要調用 render 方法重新描繪 dom。因為 dom 的描繪非常消耗性能,如果我們能在 shouldComponentUpdate 方法中能夠寫出更優(yōu)化的 dom diff 算法,可以極大的提高性能。
9.為什么虛擬dom會提高性能?
答:虛擬dom相當于在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的dom操作,從而提高性能。
用javascript對象結構表示Dom樹的結構:然后用這個樹構建一個真正的Dom樹,插到文檔當中當狀態(tài)變更的時候,重新構造一顆新的對象樹。然后用新的樹和舊的樹進行比較,記錄兩棵樹差異把2所記錄的差異應用到步驟1所構建的真正的Dom樹上,視圖就更新了。
10.React 中 refs 的作用是什么?
答:Refs 是 React 提供給我們的安全訪問 DOM 元素或者某個組件實例的句柄。
我們可以為元素添加 ref 屬性然后在回調函數中接受該元素在 DOM 樹中的句柄,該值會作為回調函數的第一個參數返回:
class CustomForm extends 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 指針以便在其他的類函數中使用。
另外值得一提的是,refs 并不是類組件的專屬,函數式組件同樣能夠利用閉包暫存其值:
function CustomForm({ handleSubmit }) {
let inputElement;
return (
<form onSubmit={() => handleSubmit(inputElement.value)}>
<input type='text' ref={input => (inputElement = input)} />
<button type='submit'>Submit</button>
</form?
);
}
11.setState 和 replaceState 的區(qū)別
答:setState 是修改其中的部分狀態(tài),相當于 Object.assign,只是覆蓋,
不會減少原來的狀態(tài); replaceState 是完全替換原來的狀態(tài),相當于賦值,將原來的 state 替換為另一個對象,如果新狀態(tài)屬性減少,那么 state 中就沒有這個狀態(tài)了。
12.React 中有三種構建組件的方式
答:React.createClass()、ES6 class 和無狀態(tài)函數。
13.描述事件在 React 中的處理方式
答:為了解決跨瀏覽器兼容性問題,您的 React 中的事件處理程序將傳遞 SyntheticEvent 的實例,它是 React 的瀏覽器本機事件的跨瀏覽器包裝器。
這些 SyntheticEvent 與您習慣的原生事件具有相同的接口,除了它們在所有瀏覽器中都兼容。
有趣的是,React 實際上并沒有將事件附加到子節(jié)點本身。
React 將使用單個事件監(jiān)聽器監(jiān)聽頂層的所有事件。
這對于性能是有好處的,這也意味著在更新 DOM 時,React 不需要擔心跟蹤事件監(jiān)聽器。
14.應該在 React 組件的何處發(fā)起 Ajax 請求
答:在 React 組件中,應該在 componentDidMount 中發(fā)起網絡請求。這個方法會在組件第一次“掛載”(被添加到 DOM)時執(zhí)行,在組件的生命周期中僅會執(zhí)行一次。
更重要的是,你不能保證在組件掛載之前 Ajax 請求已經完成,如果是這樣,也就意味著你將嘗試在一個未掛載的組件上調用 setState,這將不起作用。
在 componentDidMount 中發(fā)起網絡請求將保證這有一個組件可以更新了。
15.調用 super(props) 的目的是什么
答:在 super() 被調用之前,子類是不能使用 this 的,在 ES2015 中,子類必須在 constructor 中調用 super()。
傳遞 props 給 super() 的原因則是便于(在子類中)能在 constructor 訪問 this.props。
16.除了在構造函數中綁定 this,還有其它方式嗎
答:可以使用屬性初始值設定項(property initializers)來正確綁定回調,create-react-app 也是默認支持的。
在回調中你可以使用箭頭函數,但問題是每次組件渲染時都會創(chuàng)建一個新的回調。
17.為什么setState 的參數是一個 callback 而不是一個對象
答:因為 this.props 和 this.state 的更新可能是異步的,不能依賴它們的值去計算下一個 state。
18.在 React 當中 Element 和 Component 有何區(qū)別?
答:React Element 是描述屏幕上所見內容的數據結構,是對于 UI 的對象表述。
典型的 React Element 就是利用 JSX 構建的聲明式代碼片然后被轉化createElement 的調用組合。
React Component 是一個函數或一個類,可以接收參數輸入,并且返回某個 React Element
19.狀態(tài)(state)和屬性(props)之間有何區(qū)別
答:State 是一種數據結構,用于組件掛載時所需數據的默認值。
State 可能會隨著時間的推移而發(fā)生突變,但多數時候是作為用戶事件行為的結果。
Props(properties 的簡寫)則是組件的配置。props 由父組件傳遞給子組件,并且就子組件而言,props 是不可變的(immutable)。
組件不能改變自身的 props,但是可以把其子組件的 props 放在一起(統一管理)。Props 也不僅僅是數據,回調函數也可以通過 props 傳遞。
20.createElement 和 cloneElement 有什么區(qū)別?
答:
傳入的第一個參數不同
React.createElement():JSX 語法就是用React.createElement()來構建 React 元素的。
它接受三個參數,第一個參數可以是一個標簽名。如 div、span,或者 React 組件。第二個參數為傳入的屬性。第三個以及之后的參數,皆作為組件的子組件。
React.createElement(type, [props], [...children]);React.cloneElement()與 React.createElement()相似,不同的是它傳入的 第一個參數是一個React元素,而不是標簽名或組件。新添加 的屬性會并入原有的屬性,傳入到返回的新元素中,而舊的子元素將被替換。將保留原始元素的鍵和引用。
React.cloneElement(element, [props], [...children]);