常見react面試題

React 中 keys 的作用是什么?

Keys 是 React 用于追蹤哪些列表中元素被修改、被添加或者被移除的輔助標識。

render () {return(? ?

    ? ? ? {this.state.todoItems.map(({item, key}) => {return
  • {item}
  • ? ? ? })}? ?
? )}

在開發(fā)過程中,我們需要保證某個元素的 key 在其同級元素中具有唯一性。在 React Diff 算法中 React 會借助元素的 Key 值來判斷該元素是新近創(chuàng)建的還是被移動而來的元素削罩,從而減少不必要的元素重渲染。此外趾疚,React 還需要借助 Key 值來判斷元素與本地狀態(tài)的關聯(lián)關系赡磅,因此我們絕不可忽視轉換函數(shù)中 Key 的重要性冶匹。



調用 setState 之后發(fā)生了什么飞蛹?

在代碼中調用 setState 函數(shù)之后幢炸,React 會將傳入的參數(shù)對象與組件當前的狀態(tài)合并,然后觸發(fā)所謂的調和過程(Reconciliation)。經過調和過程,React 會以相對高效的方式根據(jù)新的狀態(tài)構建 React 元素樹并且著手重新渲染整個 UI 界面。在 React 得到元素樹之后,React 會自動計算出新的樹與老樹的節(jié)點差異,然后根據(jù)差異對界面進行最小化重渲染。在差異計算算法中,React 能夠相對精確地知道哪些位置發(fā)生了改變以及應該如何改變辈毯,這就保證了按需更新唁影,而不是全部重新渲染。



react 生命周期函數(shù)

初始化階段:

getDefaultProps:獲取實例的默認屬性

getInitialState:獲取每個實例的初始化狀態(tài)

componentWillMount:組件即將被裝載猾警、渲染到頁面上

render:組件在這里生成虛擬的 DOM 節(jié)點

componentDidMount:組件真正在被裝載之后

運行中狀態(tài):

componentWillReceiveProps:組件將要接收到屬性的時候調用

shouldComponentUpdate:組件接受到新屬性或者新狀態(tài)的時候(可以返回 false穴墅,接收數(shù)據(jù)后不更新,阻止 render 調用券躁,后面的函數(shù)不會被繼續(xù)執(zhí)行了)

componentWillUpdate:組件即將更新不能修改屬性和狀態(tài)

render:組件重新描繪

componentDidUpdate:組件已經更新

銷毀階段:

componentWillUnmount:組件即將銷毀

shouldComponentUpdate 是做什么的慢哈,(react 性能優(yōu)化是哪個周期函數(shù)滥沫?)

shouldComponentUpdate 這個方法用來判斷是否需要調用 render 方法重新描繪 dom世分。因為 dom 的描繪非常消耗性能,如果我們能在 shouldComponentUpdate 方法中能夠寫出更優(yōu)化的 dom diff 算法,可以極大的提高性能。

參考react 性能優(yōu)化-sf

為什么虛擬 dom 會提高性能?(必考)

虛擬 dom 相當于在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法避免了沒有必要的 dom 操作痹束,從而提高性能。

用 JavaScript 對象結構表示 DOM 樹的結構;然后用這個樹構建一個真正的 DOM 樹嘉汰,插到文檔當中當狀態(tài)變更的時候,重新構造一棵新的對象樹。然后用新的樹和舊的樹進行比較,記錄兩棵樹差異把 2 所記錄的差異應用到步驟 1 所構建的真正的 DOM 樹上抛猫,視圖就更新了掖看。

參考?如何理解虛擬 DOM?-zhihu

react diff 原理(骋愦考,大廠必考)

把樹形結構按照層級分解悯森,只比較同級元素墩莫。

給列表結構的每個單元添加唯一的 key 屬性推捐,方便比較。

React 只會匹配相同 class 的 component(這里面的 class 指的是組件的名字)

合并操作符喝,調用 component 的 setState 方法的時候, React 將其標記為 dirty.到每一個事件循環(huán)結束, React 檢查所有標記 dirty 的 component 重新繪制.

選擇性子樹渲染缴川。開發(fā)人員可以重寫 shouldComponentUpdate 提高 diff 的性能铭污。

參考:React 的 diff 算法

React 中 refs 的作用是什么?

Refs 是 React 提供給我們的安全訪問 DOM 元素或者某個組件實例的句柄嘹狞。我們可以為元素添加 ref 屬性然后在回調函數(shù)中接受該元素在 DOM 樹中的句柄岂膳,該值會作為回調函數(shù)的第一個參數(shù)返回:

classCustomFormextendsComponent{? handleSubmit = () => {? ? console.log("Input Value: ",this.input.value)? }? render () {return(? ? ? ? ? ? ? this.input = input} />? ? ? ? Submit? ? ? ? ? )? }}

上述代碼中的 input 域包含了一個 ref 屬性,該屬性聲明的回調函數(shù)會接收 input 對應的 DOM 元素磅网,我們將其綁定到 this 指針以便在其他的類函數(shù)中使用谈截。另外值得一提的是,refs 并不是類組件的專屬涧偷,函數(shù)式組件同樣能夠利用閉包暫存其值:

functionCustomForm({handleSubmit}){letinputElementreturn(handleSubmit(inputElement.value)}>inputElement = input} />Submit)}

如果你創(chuàng)建了類似于下面的 Twitter 元素簸喂,那么它相關的類定義是啥樣子的?

{(user) => user === null? ? ?:}

importReact, {Component,PropTypes} from'react'importfetchUser from'twitter'// fetchUser take in a username returns a promise// which will resolve with that username's data.classTwitterextendsComponent{// finish this}

如果你還不熟悉回調渲染模式(Render Callback Pattern)燎潮,這個代碼可能看起來有點怪喻鳄。這種模式中,組件會接收某個函數(shù)作為其子組件跟啤,然后在渲染函數(shù)中以 props.children 進行調用:

importReact, {Component,PropTypes} from'react'importfetchUser from'twitter'classTwitterextendsComponent{? state = {? ? user:null,? }? static propTypes = {? ? username:PropTypes.string.isRequired,? }? componentDidMount () {? ? fetchUser(this.props.username)? ? ? .then((user) =>this.setState({user}))? }? render () {returnthis.props.children(this.state.user)? }}

這種模式的優(yōu)勢在于將父組件與子組件解耦和诽表,父組件可以直接訪問子組件的內部狀態(tài)而不需要再通過 Props 傳遞,這樣父組件能夠更為方便地控制子組件展示的 UI 界面隅肥。譬如產品經理讓我們將原本展示的 Badge 替換為 Profile竿奏,我們可以輕易地修改下回調函數(shù)即可:

{(user) => user === null? ? ?:}

展示組件(Presentational component)和容器組件(Container component)之間有何不同

展示組件關心組件看起來是什么。展示專門通過 props 接受數(shù)據(jù)和回調腥放,并且?guī)缀醪粫凶陨淼臓顟B(tài)泛啸,但當展示組件擁有自身的狀態(tài)時,通常也只關心 UI 狀態(tài)而不是數(shù)據(jù)的狀態(tài)秃症。

容器組件則更關心組件是如何運作的候址。容器組件會為展示組件或者其它容器組件提供數(shù)據(jù)和行為(behavior),它們會調用 Flux actions种柑,并將其作為回調提供給展示組件岗仑。容器組件經常是有狀態(tài)的,因為它們是(其它組件的)數(shù)據(jù)源聚请。

類組件(Class component)和函數(shù)式組件(Functional component)之間有何不同

類組件不僅允許你使用更多額外的功能荠雕,如組件自身的狀態(tài)和生命周期鉤子稳其,也能使組件直接訪問 store 并維持狀態(tài)

當組件僅是接收 props,并將組件自身渲染到頁面時炸卑,該組件就是一個 '無狀態(tài)組件(stateless component)'既鞠,可以使用一個純函數(shù)來創(chuàng)建這樣的組件。這種組件也被稱為啞組件(dumb components)或展示組件

(組件的)狀態(tài)(state)和屬性(props)之間有何不同

State 是一種數(shù)據(jù)結構盖文,用于組件掛載時所需數(shù)據(jù)的默認值嘱蛋。State 可能會隨著時間的推移而發(fā)生突變,但多數(shù)時候是作為用戶事件行為的結果五续。

Props(properties 的簡寫)則是組件的配置洒敏。props 由父組件傳遞給子組件,并且就子組件而言返帕,props 是不可變的(immutable)桐玻。組件不能改變自身的 props,但是可以把其子組件的 props 放在一起(統(tǒng)一管理)荆萤。Props 也不僅僅是數(shù)據(jù)--回調函數(shù)也可以通過 props 傳遞镊靴。

何為受控組件(controlled component)

在 HTML 中,類似?<input>,?<textarea>?和?<select>?這樣的表單元素會維護自身的狀態(tài)链韭,并基于用戶的輸入來更新偏竟。當用戶提交表單時,前面提到的元素的值將隨表單一起被發(fā)送敞峭。但在 React 中會有些不同踊谋,包含表單元素的組件將會在 state 中追蹤輸入的值,并且每次調用回調函數(shù)時旋讹,如 onChange 會更新 state殖蚕,重新渲染組件。一個輸入表單元素沉迹,它的值通過 React 的這種方式來控制睦疫,這樣的元素就被稱為"受控元素"。

何為高階組件(higher order component)

高階組件是一個以組件為參數(shù)并返回一個新組件的函數(shù)鞭呕。HOC 運行你重用代碼蛤育、邏輯和引導抽象。最常見的可能是 Redux 的 connect 函數(shù)葫松。除了簡單分享工具庫和簡單的組合瓦糕,HOC 最好的方式是共享 React 組件之間的行為。如果你發(fā)現(xiàn)你在不同的地方寫了大量代碼來做同一件事時腋么,就應該考慮將代碼重構為可重用的 HOC咕娄。

為什么建議傳遞給 setState 的參數(shù)是一個 callback 而不是一個對象

因為 this.props 和 this.state 的更新可能是異步的,不能依賴它們的值去計算下一個 state珊擂。

除了在構造函數(shù)中綁定 this圣勒,還有其它方式嗎

你可以使用屬性初始值設定項(property initializers)來正確綁定回調徐块,create-react-app 也是默認支持的。在回調中你可以使用箭頭函數(shù)灾而,但問題是每次組件渲染時都會創(chuàng)建一個新的回調。

(在構造函數(shù)中)調用 super(props) 的目的是什么

在 super() 被調用之前扳剿,子類是不能使用 this 的旁趟,在 ES2015 中,子類必須在 constructor 中調用 super()庇绽。傳遞 props 給 super() 的原因則是便于(在子類中)能在 constructor 訪問 this.props锡搜。

應該在 React 組件的何處發(fā)起 Ajax 請求

在 React 組件中,應該在 componentDidMount 中發(fā)起網(wǎng)絡請求瞧掺。這個方法會在組件第一次“掛載”(被添加到 DOM)時執(zhí)行耕餐,在組件的生命周期中僅會執(zhí)行一次。更重要的是辟狈,你不能保證在組件掛載之前 Ajax 請求已經完成肠缔,如果是這樣,也就意味著你將嘗試在一個未掛載的組件上調用 setState哼转,這將不起作用明未。在 componentDidMount 中發(fā)起網(wǎng)絡請求將保證這有一個組件可以更新了。

描述事件在 React 中的處理方式壹蔓。

為了解決跨瀏覽器兼容性問題趟妥,您的 React 中的事件處理程序將傳遞 SyntheticEvent 的實例,它是 React 的瀏覽器本機事件的跨瀏覽器包裝器佣蓉。

這些 SyntheticEvent 與您習慣的原生事件具有相同的接口披摄,除了它們在所有瀏覽器中都兼容。有趣的是勇凭,React 實際上并沒有將事件附加到子節(jié)點本身疚膊。React 將使用單個事件監(jiān)聽器監(jiān)聽頂層的所有事件。這對于性能是有好處的套像,這也意味著在更新 DOM 時酿联,React 不需要擔心跟蹤事件監(jiān)聽器。

createElement 和 cloneElement 有什么區(qū)別夺巩?

React.createElement():JSX 語法就是用 React.createElement()來構建 React 元素的贞让。它接受三個參數(shù),第一個參數(shù)可以是一個標簽名柳譬。如 div喳张、span,或者 React 組件美澳。第二個參數(shù)為傳入的屬性销部。第三個以及之后的參數(shù)摸航,皆作為組件的子組件。

React.createElement(type,[props],[...children])

React.cloneElement()與 React.createElement()相似舅桩,不同的是它傳入的第一個參數(shù)是一個 React 元素酱虎,而不是標簽名或組件。新添加的屬性會并入原有的屬性擂涛,傳入到返回的新元素中读串,而就的子元素獎杯替換。

React.cloneElement(element,[props],[...children])

React 中有三種構建組件的方式

React.createClass()撒妈、ES6 class 和無狀態(tài)函數(shù)恢暖。

react 組件的劃分業(yè)務組件技術組件?

根據(jù)組件的職責通常把組件分為 UI 組件和容器組件狰右。

UI 組件負責 UI 的呈現(xiàn)杰捂,容器組件負責管理數(shù)據(jù)和邏輯。

兩者通過 React-Redux 提供 connect 方法聯(lián)系起來棋蚌。

簡述 flux 思想

Flux 的最大特點嫁佳,就是數(shù)據(jù)的"單向流動"。

用戶訪問 View

View 發(fā)出用戶的 Action

Dispatcher 收到 Action谷暮,要求 Store 進行相應的更新

Store 更新后脱拼,發(fā)出一個"change"事件

View 收到"change"事件后,更新頁面


了解 redux 么坷备,說一下 redux 把

redux 是一個應用數(shù)據(jù)流框架熄浓,主要是解決了組件間狀態(tài)共享的問題,原理是集中式管理省撑,主要有三個核心方法赌蔑,action,store竟秫,reducer娃惯,工作流程是 view 調用 store 的 dispatch 接收 action 傳入 store,reducer 進行 state 操作肥败,view 通過 store 提供的 getState 獲取最新的數(shù)據(jù)趾浅,flux 也是用來進行數(shù)據(jù)操作的,有四個組成部分 action馒稍,dispatch皿哨,view,store纽谒,工作流程是 view 發(fā)出一個 action证膨,派發(fā)器接收 action,讓 store 進行數(shù)據(jù)更新鼓黔,更新完成以后 store 發(fā)出 change央勒,view 接受 change 更新視圖不见。Redux 和 Flux 很像。主要區(qū)別在于 Flux 有多個可以改變應用狀態(tài)的 store崔步,在 Flux 中 dispatcher 被用來傳遞數(shù)據(jù)到注冊的回調事件稳吮,但是在 redux 中只能定義一個可更新狀態(tài)的 store,redux 把 store 和 Dispatcher 合并,結構更加簡單清晰

新增 state,對狀態(tài)的管理更加明確井濒,通過 redux盖高,流程更加規(guī)范了,減少手動編碼量眼虱,提高了編碼效率,同時缺點時當數(shù)據(jù)更新時有時候組件不需要席纽,但是也要重新繪制捏悬,有些影響效率。一般情況下润梯,我們在構建多交互过牙,多數(shù)據(jù)流的復雜項目應用時才會使用它們

redux 有什么缺點

一個組件所需要的數(shù)據(jù),必須由父組件傳過來纺铭,而不能像 flux 中直接從 store 取寇钉。

當一個組件相關數(shù)據(jù)更新時,即使父組件不需要用到這個組件舶赔,父組件還是會重新 render扫倡,可能會有效率影響,或者需要寫復雜的 shouldComponentUpdate 進行判斷竟纳。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末撵溃,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子锥累,更是在濱河造成了極大的恐慌缘挑,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桶略,死亡現(xiàn)場離奇詭異语淘,居然都是意外死亡,警方通過查閱死者的電腦和手機际歼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門惶翻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹅心,你說我怎么就攤上這事维贺。” “怎么了巴帮?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵溯泣,是天一觀的道長虐秋。 經常有香客問我,道長垃沦,這世上最難降的妖魔是什么客给? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮肢簿,結果婚禮上靶剑,老公的妹妹穿的比我還像新娘。我一直安慰自己池充,他們只是感情好桩引,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著收夸,像睡著了一般坑匠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上卧惜,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天厘灼,我揣著相機與錄音,去河邊找鬼咽瓷。 笑死设凹,一個胖子當著我的面吹牛,可吹牛的內容都是我干的茅姜。 我是一名探鬼主播闪朱,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钻洒!你這毒婦竟也來了监透?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤航唆,失蹤者是張志新(化名)和其女友劉穎胀蛮,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糯钙,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡粪狼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了任岸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片再榄。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖享潜,靈堂內的尸體忽然破棺而出困鸥,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布疾就,位于F島的核電站澜术,受9級特大地震影響,放射性物質發(fā)生泄漏猬腰。R本人自食惡果不足惜鸟废,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望姑荷。 院中可真熱鬧盒延,春花似錦、人聲如沸鼠冕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懈费。三九已至计露,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間楞捂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工趋厉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寨闹,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓君账,卻偏偏與公主長得像繁堡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子乡数,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容