不可錯(cuò)過(guò)的Rect面試題,務(wù)必收藏
下面是一個(gè)常用的關(guān)于 React 的面試問(wèn)題列表:
無(wú)論作為一個(gè)面試者,或者招聘官,下面這些問(wèn)題都可以去參考。
React 的工作原理
React 會(huì)創(chuàng)建一個(gè)虛擬 DOM(virtual DOM)。當(dāng)一個(gè)組件中的狀態(tài)改變時(shí),React 首先會(huì)通過(guò) "diffing" 算法來(lái)標(biāo)記虛擬 DOM 中的改變,第二步是調(diào)節(jié)(reconciliation),會(huì)用 diff 的結(jié)果來(lái)更新 DOM。
使用 React 有何優(yōu)點(diǎn)
- 只需查看 render 函數(shù)就會(huì)很容易知道一個(gè)組件是如何被渲染的
- JSX 的引入,使得組件的代碼更加可讀,也更容易看懂組件的布局,或者組件之間是如何互相引用的
- 支持服務(wù)端渲染,這可以改進(jìn) SEO 和性能
- 易于測(cè)試
- React 只關(guān)注 View 層,所以可以和其它任何框架(如Backbone.js, Angular.js)一起使用
展示組件(Presentational component)和容器組件(Container component)之間有何不同
展示組件關(guān)心組件看起來(lái)是什么。展示專(zhuān)門(mén)通過(guò) props 接受數(shù)據(jù)和回調(diào),并且?guī)缀醪粫?huì)有自身的狀態(tài),但當(dāng)展示組件擁有自身的狀態(tài)時(shí),通常也只關(guān)心 UI 狀態(tài)而不是數(shù)據(jù)的狀態(tài)。
容器組件則更關(guān)心組件是如何運(yùn)作的。容器組件會(huì)為展示組件或者其它容器組件提供數(shù)據(jù)和行為(behavior),它們會(huì)調(diào)用 Flux actions,并將其作為回調(diào)提供給展示組件。容器組件經(jīng)常是有狀態(tài)的,因?yàn)樗鼈兪?其它組件的)數(shù)據(jù)源。
類(lèi)組件(Class component)和函數(shù)式組件(Functional component)之間有何不同
- 類(lèi)組件不僅允許你使用更多額外的功能,如組件自身的狀態(tài)和生命周期鉤子,也能使組件直接訪問(wèn) store 并維持狀態(tài)
- 當(dāng)組件僅是接收 props,并將組件自身渲染到頁(yè)面時(shí),該組件就是一個(gè) '無(wú)狀態(tài)組件(stateless component)',可以使用一個(gè)純函數(shù)來(lái)創(chuàng)建這樣的組件。這種組件也被稱(chēng)為啞組件(dumb components)或展示組件
(組件的)狀態(tài)(state)和屬性(props)之間有何不同
State 是一種數(shù)據(jù)結(jié)構(gòu),用于組件掛載時(shí)所需數(shù)據(jù)的默認(rèn)值。State 可能會(huì)隨著時(shí)間的推移而發(fā)生突變,但多數(shù)時(shí)候是作為用戶事件行為的結(jié)果。
Props(properties 的簡(jiǎn)寫(xiě))則是組件的配置。props 由父組件傳遞給子組件,并且就子組件而言,props 是不可變的(immutable)。組件不能改變自身的 props,但是可以把其子組件的 props 放在一起(統(tǒng)一管理)。Props 也不僅僅是數(shù)據(jù)--回調(diào)函數(shù)也可以通過(guò) props 傳遞。
指出(組件)生命周期方法的不同
- componentWillMount -- 多用于根組件中的應(yīng)用程序配置
- componentDidMount -- 在這可以完成所有沒(méi)有 DOM 就不能做的所有配置,并開(kāi)始獲取所有你需要的數(shù)據(jù);如果需要設(shè)置事件監(jiān)聽(tīng),也可以在這完成
- omponentWillReceiveProps -- 這個(gè)周期函數(shù)作用于特定的 prop 改變導(dǎo)致的 state 轉(zhuǎn)換
- shouldComponentUpdate -- 如果你擔(dān)心組件過(guò)度渲染,shouldComponentUpdate 是一個(gè)改善性能的地方,因?yàn)槿绻M件接收了新的 prop, 它可以阻止(組件)重新渲染。shouldComponentUpdate 應(yīng)該返回一個(gè)布爾值來(lái)決定組件是否要重新渲染
- componentWillUpdate -- 很少使用。它可以用于代替組件的 componentWillReceiveProps 和 shouldComponentUpdate(但不能訪問(wèn)之前的 props)
- componentDidUpdate -- 常用于更新 DOM,響應(yīng) prop 或 state 的改變
- componentWillUnmount -- 在這你可以取消網(wǎng)絡(luò)請(qǐng)求,或者移除所有與組件相關(guān)的事件監(jiān)聽(tīng)器
應(yīng)該在 React 組件的何處發(fā)起 Ajax 請(qǐng)求
在 React 組件中,應(yīng)該在 componentDidMount 中發(fā)起網(wǎng)絡(luò)請(qǐng)求。這個(gè)方法會(huì)在組件***次“掛載”(被添加到 DOM)時(shí)執(zhí)行,在組件的生命周期中僅會(huì)執(zhí)行一次。更重要的是,你不能保證在組件掛載之前 Ajax 請(qǐng)求已經(jīng)完成,如果是這樣,也就意味著你將嘗試在一個(gè)未掛載的組件上調(diào)用 setState,這將不起作用。在 componentDidMount 中發(fā)起網(wǎng)絡(luò)請(qǐng)求將保證這有一個(gè)組件可以更新了。
何為受控組件(controlled component)
在 HTML 中,類(lèi)似 <input>, <textarea> 和 <select> 這樣的表單元素會(huì)維護(hù)自身的狀態(tài),并基于用戶的輸入來(lái)更新。當(dāng)用戶提交表單時(shí),前面提到的元素的值將隨表單一起被發(fā)送。但在 React 中會(huì)有些不同,包含表單元素的組件將會(huì)在 state 中追蹤輸入的值,并且每次調(diào)用回調(diào)函數(shù)時(shí),如 onChange 會(huì)更新 state,重新渲染組件。一個(gè)輸入表單元素,它的值通過(guò) React 的這種方式來(lái)控制,這樣的元素就被稱(chēng)為"受控元素"。
在 React 中,refs 的作用是什么
Refs 可以用于獲取一個(gè) DOM 節(jié)點(diǎn)或者 React 組件的引用。何時(shí)使用 refs 的好的示例有管理焦點(diǎn)/文本選擇,觸發(fā)命令動(dòng)畫(huà),或者和第三方 DOM 庫(kù)集成。你應(yīng)該避免使用 String 類(lèi)型的 Refs 和內(nèi)聯(lián)的 ref 回調(diào)。Refs 回調(diào)是 React 所推薦的。
何為高階組件(higher order component)
高階組件是一個(gè)以組件為參數(shù)并返回一個(gè)新組件的函數(shù)。HOC 運(yùn)行你重用代碼、邏輯和引導(dǎo)抽象。最常見(jiàn)的可能是 Redux 的 connect 函數(shù)。除了簡(jiǎn)單分享工具庫(kù)和簡(jiǎn)單的組合,HOC***的方式是共享 React 組件之間的行為。如果你發(fā)現(xiàn)你在不同的地方寫(xiě)了大量代碼來(lái)做同一件事時(shí),就應(yīng)該考慮將代碼重構(gòu)為可重用的 HOC。
練習(xí)
- 寫(xiě)一個(gè)反轉(zhuǎn)其輸入的 HOC
- 寫(xiě)一個(gè)從 API 提供數(shù)據(jù)給傳入的組件的 HOC
- 寫(xiě)一個(gè)實(shí)現(xiàn) shouldComponentUpdate 來(lái)避免 reconciliation 的 HOC
- 寫(xiě)一個(gè)通過(guò) React.Children.toArray 對(duì)傳入組件的子組件進(jìn)行排序的 HOC
使用箭頭函數(shù)(arrow functions)的優(yōu)點(diǎn)是什么
- 作用域安全:在箭頭函數(shù)之前,每一個(gè)新創(chuàng)建的函數(shù)都有定義自身的 this 值(在構(gòu)造函數(shù)中是新對(duì)象;在嚴(yán)格模式下,函數(shù)調(diào)用中的 this 是未定義的;如果函數(shù)被稱(chēng)為“對(duì)象方法”,則為基礎(chǔ)對(duì)象等),但箭頭函數(shù)不會(huì),它會(huì)使用封閉執(zhí)行上下文的 this 值。
- 簡(jiǎn)單:箭頭函數(shù)易于閱讀和書(shū)寫(xiě)
- 清晰:當(dāng)一切都是一個(gè)箭頭函數(shù),任何常規(guī)函數(shù)都可以立即用于定義作用域。開(kāi)發(fā)者總是可以查找 next-higher 函數(shù)語(yǔ)句,以查看 this 的值
為什么建議傳遞給 setState 的參數(shù)是一個(gè) callback 而不是一個(gè)對(duì)象
因?yàn)?this.props 和 this.state 的更新可能是異步的,不能依賴(lài)它們的值去計(jì)算下一個(gè) state。
除了在構(gòu)造函數(shù)中綁定 this,還有其它方式嗎
你可以使用屬性初始值設(shè)定項(xiàng)(property initializers)來(lái)正確綁定回調(diào),create-react-app 也是默認(rèn)支持的。在回調(diào)中你可以使用箭頭函數(shù),但問(wèn)題是每次組件渲染時(shí)都會(huì)創(chuàng)建一個(gè)新的回調(diào)。
怎么阻止組件的渲染
在組件的 render 方法中返回 null 并不會(huì)影響觸發(fā)組件的生命周期方法
當(dāng)渲染一個(gè)列表時(shí),何為 key?設(shè)置 key 的目的是什么
Keys 會(huì)有助于 React 識(shí)別哪些 items 改變了,被添加了或者被移除了。Keys 應(yīng)該被賦予數(shù)組內(nèi)的元素以賦予(DOM)元素一個(gè)穩(wěn)定的標(biāo)識(shí),選擇一個(gè) key 的***方法是使用一個(gè)字符串,該字符串能惟一地標(biāo)識(shí)一個(gè)列表項(xiàng)。很多時(shí)候你會(huì)使用數(shù)據(jù)中的 IDs 作為 keys,當(dāng)你沒(méi)有穩(wěn)定的 IDs 用于被渲染的 items 時(shí),可以使用項(xiàng)目索引作為渲染項(xiàng)的 key,但這種方式并不推薦,如果 items 可以重新排序,就會(huì)導(dǎo)致 re-render 變慢。
(在構(gòu)造函數(shù)中)調(diào)用 super(props) 的目的是什么
在 super() 被調(diào)用之前,子類(lèi)是不能使用 this 的,在 ES2015 中,子類(lèi)必須在 constructor 中調(diào)用 super()。傳遞 props 給 super() 的原因則是便于(在子類(lèi)中)能在 constructor 訪問(wèn) this.props。
何為 JSX
JSX 是 JavaScript 語(yǔ)法的一種語(yǔ)法擴(kuò)展,并擁有 JavaScript 的全部功能。JSX 生產(chǎn) React "元素",你可以將任何的 JavaScript 表達(dá)式封裝在花括號(hào)里,然后將其嵌入到 JSX 中。在編譯完成之后,JSX 表達(dá)式就變成了常規(guī)的 JavaScript 對(duì)象,這意味著你可以在 if 語(yǔ)句和 for 循環(huán)內(nèi)部使用 JSX,將它賦值給變量,接受它作為參數(shù),并從函數(shù)中返回它。
怎么用 React.createElement 重寫(xiě)下面的代碼
Question:
- const element = (
- <h1 className="greeting">
- Hello, rdhub.cn!
- </h1>
- );
Answer:
- const element = React.createElement(
- 'h1',
- {className: 'greeting'},
- 'Hello, rdhub.cn!'
- );
何為 Children
在JSX表達(dá)式中,一個(gè)開(kāi)始標(biāo)簽(比如<a>)和一個(gè)關(guān)閉標(biāo)簽(比如</a>)之間的內(nèi)容會(huì)作為一個(gè)特殊的屬性props.children被自動(dòng)傳遞給包含著它的組件。
這個(gè)屬性有許多可用的方法,包括 React.Children.map,React.Children.forEach, React.Children.count, React.Children.only,React.Children.toArray。
在 React 中,何為 state
State 和 props 類(lèi)似,但它是私有的,并且完全由組件自身控制。State 本質(zhì)上是一個(gè)持有數(shù)據(jù),并決定組件如何渲染的對(duì)象。
什么原因會(huì)促使你脫離 create-react-app 的依賴(lài)
當(dāng)你想去配置 webpack 或 babel presets。
何為 redux
Redux 的基本思想是整個(gè)應(yīng)用的 state 保持在一個(gè)單一的 store 中。store 就是一個(gè)簡(jiǎn)單的 javascript 對(duì)象,而改變應(yīng)用 state 的唯一方式是在應(yīng)用中觸發(fā) actions,然后為這些 actions 編寫(xiě) reducers 來(lái)修改 state。整個(gè) state 轉(zhuǎn)化是在 reducers 中完成,并且不應(yīng)該有任何副作用。
在 Redux 中,何為 store
Store 是一個(gè) javascript 對(duì)象,它保存了整個(gè)應(yīng)用的 state。與此同時(shí),Store 也承擔(dān)以下職責(zé):
- 允許通過(guò) getState() 訪問(wèn) state
- 運(yùn)行通過(guò) dispatch(action) 改變 state
- 通過(guò) subscribe(listener) 注冊(cè) listeners
- 通過(guò) subscribe(listener) 返回的函數(shù)處理 listeners 的注銷(xiāo)
何為 action
Actions 是一個(gè)純 javascript 對(duì)象,它們必須有一個(gè) type 屬性表明正在執(zhí)行的 action 的類(lèi)型。實(shí)質(zhì)上,action 是將數(shù)據(jù)從應(yīng)用程序發(fā)送到 store 的有效載荷。
何為 reducer
一個(gè) reducer 是一個(gè)純函數(shù),該函數(shù)以先前的 state 和一個(gè) action 作為參數(shù),并返回下一個(gè) state。
Redux Thunk 的作用是什么
Redux thunk 是一個(gè)允許你編寫(xiě)返回一個(gè)函數(shù)而不是一個(gè) action 的 actions creators 的中間件。如果滿足某個(gè)條件,thunk 則可以用來(lái)延遲 action 的派發(fā)(dispatch),這可以處理異步 action 的派發(fā)(dispatch)。
何為純函數(shù)(pure function)
一個(gè)純函數(shù)是一個(gè)不依賴(lài)于且不改變其作用域之外的變量狀態(tài)的函數(shù),這也意味著一個(gè)純函數(shù)對(duì)于同樣的參數(shù)總是返回同樣的結(jié)果。