面試題聯(lián)盟之 React 篇
關注 入坑互聯(lián)網(wǎng) ,回復“加群”
加入我們一起學習,天天進步
1.什么是虛擬DOM?
虛擬 DOM (VDOM)是真實 DOM 在內(nèi)存中的表示。UI 的表示形式保存在內(nèi)存中,并與實際的 DOM 同步。這是一個發(fā)生在渲染函數(shù)被調(diào)用和元素在屏幕上顯示之間的步驟,整個過程被稱為調(diào)和。
2.React有什么特點?
①它使用虛擬DOM而不是真正的DOM。
②它可以用服務器端渲染。
③它遵循單向數(shù)據(jù)流或數(shù)據(jù)綁定。
3.React主要優(yōu)點
①它提高了應用的性能
②可以方便地在客戶端和服務器端使用
③由于 JSX,代碼的可讀性很好
④React 很容易與 Meteor,Angular 等其他框架集成
⑤使用React,編寫UI測試用例變得非常容易
4.React有哪些限制?
①React 只是一個庫,而不是一個完整的框架
②它的庫非常龐大,需要時間來理解
③新手程序員可能很難理解
④編碼變得復雜,因為它使用內(nèi)聯(lián)模板和 JSX
5.什么是JSX?
JSX 是J avaScript XML 的簡寫。是 React 使用的一種文件,它利用 JavaScript 的表現(xiàn)力和類似 HTML 的模板語法。這使得 HTML 文件非常容易理解。此文件能使應用非常可靠,并能夠提高其性能。下面是JSX的一個例子:
render(){return(<div><h1> Hello World from Edureka!!</h1></div>);}
6.虛擬DOM(Virtual DOM)實現(xiàn)原理?
Virtual DOM 是一個輕量級的 JavaScript 對象,它最初只是 real DOM 的副本。它是一個節(jié)點樹,它將元素、它們的屬性和內(nèi)容作為對象及其屬性。React 的渲染函數(shù)從 React 組件中創(chuàng)建一個節(jié)點樹。然后它響應數(shù)據(jù)模型中的變化來更新該樹,該變化是由用戶或系統(tǒng)完成的各種動作引起的。
Virtual DOM 工作過程有三個簡單的步驟:
①每當?shù)讓訑?shù)據(jù)發(fā)生改變時,整個 UI 都將在 Virtual DOM 描述中重新渲染。
②然后計算之前 DOM 表示與新表示的之間的差異。
③完成計算后,將只用實際更改的內(nèi)容更新 real DOM。
7.如何使瀏覽器讀取JSX
瀏覽器只能處理 JavaScript 對象,而不能讀取常規(guī) JavaScript 對象中的 JSX。所以為了使瀏覽器能夠讀取 JSX,首先,需要用像 Babel 這樣的 JSX 轉(zhuǎn)換器將 JSX 文件轉(zhuǎn)換為 JavaScript 對象,然后再將其傳給瀏覽器。
8.React生命周期是怎樣的?
目前React 16.8 +的生命周期分為三個階段,分別是掛載階段、更新階段、卸載階段
①、掛載階段:
constructor: 構造函數(shù),最先被執(zhí)行,我們通常在構造函數(shù)里初始化state對象或者給自定義方法綁定this
getDerivedStateFromProps: static getDerivedStateFromProps(nextProps, prevState),這是個靜態(tài)方法,當我們接收到新的屬性想去修改我們state,可以使用getDerivedStateFromProps
render: render函數(shù)是純函數(shù),只返回需要渲染的東西,不應該包含其它的業(yè)務邏輯,可以返回原生的DOM、React組件、Fragment、Portals、字符串和數(shù)字、Boolean和null等內(nèi)容
componentDidMount: 組件裝載之后調(diào)用,此時我們可以獲取到DOM節(jié)點并操作,比如對canvas,svg的操作,服務器請求,訂閱都可以寫在這個里面,但是記得在componentWillUnmount中取消訂閱
②、更新階段:
getDerivedStateFromProps: 此方法在更新個掛載階段都可能會調(diào)用
shouldComponentUpdate: shouldComponentUpdate(nextProps, nextState),有兩個參數(shù)nextProps和nextState,表示新的屬性和變化之后的state,返回一個布爾值,true表示會觸發(fā)重新渲染,false表示不會觸發(fā)重新渲染,默認返回true,我們通常利用此生命周期來優(yōu)化React程序性能
render: 更新階段也會觸發(fā)此生命周期
getSnapshotBeforeUpdate: getSnapshotBeforeUpdate(prevProps, prevState),這個方法在render之后,componentDidUpdate之前調(diào)用,有兩個參數(shù)prevProps和prevState,表示之前的屬性和之前的state,這個函數(shù)有一個返回值,會作為第三個參數(shù)傳給componentDidUpdate,如果你不想要返回值,可以返回null,此生命周期必須與componentDidUpdate搭配使用
componentDidUpdate: componentDidUpdate(prevProps, prevState, snapshot),該方法在getSnapshotBeforeUpdate方法之后被調(diào)用,有三個參數(shù)prevProps,prevState,snapshot,表示之前的props,之前的state,和snapshot。第三個參數(shù)是getSnapshotBeforeUpdate返回的,如果觸發(fā)某些回調(diào)函數(shù)時需要用到 DOM 元素的狀態(tài),則將對比或計算的過程遷移至 getSnapshotBeforeUpdate,然后在 componentDidUpdate 中統(tǒng)一觸發(fā)回調(diào)或更新狀態(tài)。
③、卸載階段:
componentWillUnmount: 當我們的組件被卸載或者銷毀了就會調(diào)用,我們可以在這個函數(shù)里去清除一些定時器,取消網(wǎng)絡請求,清理無效的DOM元素等垃圾清理工作
9.React的請求應該放在哪個生命周期中?
由于JavaScript中異步事件的性質(zhì),當您啟動API調(diào)用時,瀏覽器會在此期間返回執(zhí)行其他工作。當React渲染一個組件時,它不會等待componentWillMount它完成任何事情 - React繼續(xù)前進并繼續(xù)render,沒有辦法“暫停”渲染以等待數(shù)據(jù)到達。
而且在componentWillMount請求會有一系列潛在的問題,首先,在服務器渲染時,如果在 componentWillMount 里獲取數(shù)據(jù),fetch data會執(zhí)行兩次,一次在服務端一次在客戶端,這造成了多余的請求,其次,在React 16進行React Fiber重寫后,componentWillMount可能在一次渲染中多次調(diào)用.
目前官方推薦的異步請求是在componentDidmount中進行.
10.解釋 React 中 render() 的目的。
每個React組件強制要求必須有一個 render()。它返回一個 React 元素,是原生 DOM 組件的表示。如果需要渲染多個 HTML 元素,則必須將它們組合在一個封閉標記內(nèi),例如 <form>、<group>、<div>等。此函數(shù)必須保持純凈,即必須每次調(diào)用時都返回相同的結果。
11.在 React 中如何處理事件
為了解決跨瀏覽器的兼容性問題,SyntheticEvent 實例將被傳遞給你的事件處理函數(shù),SyntheticEvent是 React 跨瀏覽器的瀏覽器原生事件包裝器,它還擁有和瀏覽器原生事件相同的接口,包括 stopPropagation() 和 preventDefault()。
比較有趣的是,React 實際上并不將事件附加到子節(jié)點本身。React 使用單個事件偵聽器偵聽頂層的所有事件。這對性能有好處,也意味著 React 在更新 DOM 時不需要跟蹤事件監(jiān)聽器。
12.state 和 props 區(qū)別是啥?
props和state是普通的 JS 對象。雖然它們都包含影響渲染輸出的信息,但是它們在組件方面的功能是不同的。即
state 是組件自己管理數(shù)據(jù),控制自己的狀態(tài),可變;
props 是外部傳入的數(shù)據(jù)參數(shù),不可變;
沒有state的叫做無狀態(tài)組件,有state的叫做有狀態(tài)組件;
多用 props,少用 state,也就是多寫無狀態(tài)組件。
13.在構造函數(shù)調(diào)用 super 并將 props 作為參數(shù)傳入的作用是啥?
在調(diào)用 super() 方法之前,子類構造函數(shù)無法使用this引用,ES6 子類也是如此。將 props 參數(shù)傳遞給 super() 調(diào)用的主要原因是在子構造函數(shù)中能夠通過this.props來獲取傳入的 props。
傳遞 props
class MyComponent extends React.Component {constructor(props) {super(props);console.log(this.props); // { name: 'sudheer',age: 30 }}}
沒傳遞 props
class MyComponent extends React.Component {constructor(props) {super();console.log(this.props); // undefined// 但是 Props 參數(shù)仍然可用console.log(props); // Prints { name: 'sudheer',age: 30 }}render() {// 構造函數(shù)外部不受影響console.log(this.props) // { name: 'sudheer',age: 30 }}}
上面示例揭示了一點。props 的行為只有在構造函數(shù)中是不同的,在構造函數(shù)之外也是一樣的。
14.為什么不直接更新 state 呢 ?
如果試圖直接更新 state ,則不會重新渲染組件。
// 錯誤This.state.message = 'Hello world';
需要使用setState()方法來更新 state。它調(diào)度對組件state對象的更新。當state改變時,組件通過重新渲染來響應:
// 正確做法This.setState({message: ‘Hello World’});
15.React中的狀態(tài)是什么?它是如何使用的?
狀態(tài)是 React 組件的核心,是數(shù)據(jù)的來源,必須盡可能簡單。基本上狀態(tài)是確定組件呈現(xiàn)和行為的對象。與props 不同,它們是可變的,并創(chuàng)建動態(tài)和交互式組件。可以通過 this.state() 訪問它們。
16.如何更新組件的狀態(tài)?
可以用 this.setState()更新組件的狀態(tài)。
class MyComponent extends React.Component {constructor() {super();this.state = {name: 'Maxx',id: '101'}}render(){setTimeout(()=>{this.setState({name:'Jaeha', id:'222'})},2000)return (<div><h1>Hello {this.state.name}</h1><h2>Your Id is {this.state.id}</h2></div>);}}ReactDOM.render(<MyComponent/>, document.getElementById('content'));
17.什么是高階組件(HOC)?能用HOC做什么?
高階組件是重用組件邏輯的高級方法,是一種源于 React 的組件模式。HOC 是自定義組件,在它之內(nèi)包含另一個組件。它們可以接受子組件提供的任何動態(tài),但不會修改或復制其輸入組件中的任何行為。你可以認為 HOC 是“純(Pure)”組件。
HOC可用于許多任務,例如:
代碼重用,邏輯和引導抽象
渲染劫持
狀態(tài)抽象和控制
Props 控制
18.React 中 key 的重要性是什么?
key 用于識別唯一的 Virtual DOM 元素及其驅(qū)動 UI 的相應數(shù)據(jù)。它們通過回收 DOM 中當前所有的元素來幫助 React 優(yōu)化渲染。這些 key 必須是唯一的數(shù)字或字符串,React 只是重新排序元素而不是重新渲染它們。這可以提高應用程序的性能
19.React組件間通信方式?
父組件向子組件通訊: 父組件可以向子組件通過傳 props 的方式,向子組件進行通訊
子組件向父組件通訊: props+回調(diào)的方式,父組件向子組件傳遞props進行通訊,此props為作用域為父組件自身的函數(shù),子組件調(diào)用該函數(shù),將子組件想要傳遞的信息,作為參數(shù),傳遞到父組件的作用域中
兄弟組件通信: 找到這兩個兄弟節(jié)點共同的父節(jié)點,結合上面兩種方式由父節(jié)點轉(zhuǎn)發(fā)信息進行通信
跨層級通信: Context設計目的是為了共享那些對于一個組件樹而言是“全局”的數(shù)據(jù),例如當前認證的用戶、主題或首選語言,對于跨越多層的全局數(shù)據(jù)通過Context通信再適合不過
發(fā)布訂閱模式: 發(fā)布者發(fā)布事件,訂閱者監(jiān)聽事件并做出反應,我們可以通過引入event模塊進行通信
全局狀態(tài)管理工具: 借助Redux或者Mobx等全局狀態(tài)管理工具進行通信,這種工具會維護一個全局狀態(tài)中心Store,并根據(jù)不同的事件產(chǎn)生新的狀態(tài)
20.介紹一下什么是Redux?
Redux 是當今最熱門的前端開發(fā)庫之一。它是 JavaScript 程序的可預測狀態(tài)容器,用于整個應用的狀態(tài)管理。使用 Redux 開發(fā)的應用易于測試,可以在不同環(huán)境中運行,并顯示一致的行為。
Redux主要結構:
Store:保存數(shù)據(jù)的地方,你可以把它看成一個容器,整個應用只能有一個Store。
State:Store對象包含所有數(shù)據(jù),如果想得到某個時點的數(shù)據(jù),就要對Store生成快照,這種時點的數(shù)據(jù)集合,就叫做State。
Action:State的變化,會導致View的變化。但是,用戶接觸不到State,只能接觸到View。所以,State的變化必須是View導致的。Action就是View發(fā)出的通知,表示State應該要發(fā)生變化了。
Action Creator:View要發(fā)送多少種消息,就會有多少種Action。如果都手寫,會很麻煩,所以我們定義一個函數(shù)來生成Action,這個函數(shù)就叫Action Creator。
Reducer:Store收到Action以后,必須給出一個新的State,這樣View才會發(fā)生變化。這種State的計算過程就叫做Reducer。Reducer是一個函數(shù),它接受Action和當前State作為參數(shù),返回一個新的State。
dispatch:是View發(fā)出Action的唯一方法。
21.Redux的工作流程
首先,用戶(通過View)發(fā)出Action,發(fā)出方式就用到了dispatch方法。
然后,Store自動調(diào)用Reducer,并且傳入兩個參數(shù):當前State和收到的Action,Reducer會返回新的State
State一旦有變化,Store就會調(diào)用監(jiān)聽函數(shù),來更新View。
22.如何在 Redux 中定義 Action?
React 中的 Action 必須具有 type 屬性,該屬性指示正在執(zhí)行的 ACTION 的類型。必須將它們定義為字符串常量,并且還可以向其添加更多的屬性。在 Redux 中,action 被名為 Action Creators 的函數(shù)所創(chuàng)建。以下是 Action 和Action Creator 的示例:
function addTodo(text) {return {type: ADD_TODO,text}}
23.解釋 Reducer 的作用。
Reducers 是純函數(shù),它規(guī)定應用程序的狀態(tài)怎樣因響應 ACTION 而改變。Reducers 通過接受先前的狀態(tài)和 action 來工作,然后它返回一個新的狀態(tài)。它根據(jù)操作的類型確定需要執(zhí)行哪種更新,然后返回新的值。如果不需要完成任務,它會返回原來的狀態(tài)。
24.Redux 有哪些優(yōu)點?
結果的可預測性 - 由于總是存在一個真實來源,即 store ,因此不存在如何將當前狀態(tài)與動作和應用的其他部分同步的問題。
可維護性 - 代碼變得更容易維護,具有可預測的結果和嚴格的結構。
服務器端渲染 - 你只需將服務器上創(chuàng)建的 store 傳到客戶端即可。這對初始渲染非常有用,并且可以優(yōu)化應用性能,從而提供更好的用戶體驗。
開發(fā)人員工具 - 從操作到狀態(tài)更改,開發(fā)人員可以實時跟蹤應用中發(fā)生的所有事情。
社區(qū)和生態(tài)系統(tǒng) - Redux 背后有一個巨大的社區(qū),這使得它更加迷人。一個由才華橫溢的人組成的大型社區(qū)為庫的改進做出了貢獻,并開發(fā)了各種應用。
易于測試 - Redux 的代碼主要是小巧、純粹和獨立的功能。這使代碼可測試且獨立。
組織 - Redux 準確地說明了代碼的組織方式,這使得代碼在團隊使用時更加一致和簡單。
25.什么是React 路由?
React 路由是一個構建在 React 之上的強大的路由庫,它有助于向應用程序添加新的屏幕和流。這使 URL 與網(wǎng)頁上顯示的數(shù)據(jù)保持同步。它負責維護標準化的結構和行為,并用于開發(fā)單頁 Web 應用。React 路由有一個簡單的API。
26.為什么需要 React 中的路由?
Router 用于定義多個路由,當用戶定義特定的 URL 時,如果此 URL 與 Router 內(nèi)定義的任何 “路由” 的路徑匹配,則用戶將重定向到該特定路由。所以基本上我們需要在自己的應用中添加一個 Router 庫,允許創(chuàng)建多個路由,每個路由都會向我們提供一個獨特的視圖
<switch><route exact path=’/’ component={Home}/><route path=’/posts/:id’ component={Newpost}/><route path=’/posts’ component={Post}/></switch>
27.如何避免組件的重新渲染?
React 中最常見的問題之一是組件不必要地重新渲染。React 提供了兩個方法,在這些情況下非常有用:
React.memo():這可以防止不必要地重新渲染函數(shù)組件
PureComponent:這可以防止不必要地重新渲染類組件
這兩種方法都依賴于對傳遞給組件的props的淺比較,如果 props 沒有改變,那么組件將不會重新渲染。雖然這兩種工具都非常有用,但是淺比較會帶來額外的性能損失,因此如果使用不當,這兩種方法都會對性能產(chǎn)生負面影響。
通過使用 React Profiler,可以在使用這些方法前后對性能進行測量,從而確保通過進行給定的更改來實際改進性能。
28.react性能優(yōu)化方案
(1)重寫shouldComponentUpdate來避免不必要的dom操作。
(2)使用 production 版本的react.js。
(3)使用key來幫助React識別列表中所有子組件的最小變化。
?? 看完三件事
如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:
點贊,讓更多的人也能看到這篇內(nèi)容(收藏不點贊,都是耍流氓)。 關注公眾號「入坑互聯(lián)網(wǎng)」,不定期分享原創(chuàng)知識。 也看看其它文章
- END -
結伴同行前端路

