摘要:為了使用它們,您可以向組件添加一個(gè)屬性,該屬性的值是一個(gè)回調(diào)函數(shù),它將接收底層的元素或組件的已掛接實(shí)例,作為其第一個(gè)參數(shù)。通常最好使用另一個(gè)生命周期方法,而不是依賴這個(gè)回調(diào)函數(shù),但是很高興知道它存在。
React 常見的面試題
(在 React 里面,你可以知道也可以不知道的事, 但是你會(huì)發(fā)現(xiàn)他們確實(shí)很有用)
根據(jù)記錄,問這些問題可能不是深入了解他們在使用 React 方面的經(jīng)驗(yàn)的最佳方式。
之所以標(biāo)題是《 React 常見的面試題》,其實(shí)只是想起一個(gè)比《在 React 里面,你可以知道也可以不知道的事, 但是你會(huì)發(fā)現(xiàn)他們確實(shí)很有用》要簡單明了的標(biāo)題而已。
原文鏈接:React Interview Questions
作者: Tyler.Google Developer Expert and a partner at React Training where we teach React online
翻譯:Johann Lai
當(dāng)你調(diào)用 setState 的時(shí)候,發(fā)生了什么事?當(dāng)調(diào)用 setState 時(shí),React會(huì)做的第一件事情是將傳遞給 setState 的對象合并到組件的當(dāng)前狀態(tài)。這將啟動(dòng)一個(gè)稱為和解(reconciliation)的過程。和解(reconciliation)的最終目標(biāo)是以最有效的方式,根據(jù)這個(gè)新的狀態(tài)來更新UI。 為此,React將構(gòu)建一個(gè)新的 React 元素樹(您可以將其視為 UI 的對象表示)。
一旦有了這個(gè)樹,為了弄清 UI 如何響應(yīng)新的狀態(tài)而改變,React 會(huì)將這個(gè)新樹與上一個(gè)元素樹相比較(diff)。
通過這樣做, React 將會(huì)知道發(fā)生的確切變化,并且通過了解發(fā)生什么變化,只需在絕對必要的情況下進(jìn)行更新即可最小化 UI 的占用空間。
在 React 當(dāng)中 Element 和 Component 有何區(qū)別?簡單地說,一個(gè) React element 描述了你想在屏幕上看到什么。換個(gè)說法就是,一個(gè) React element 是一些 UI 的對象表示。
一個(gè) React Component 是一個(gè)函數(shù)或一個(gè)類,它可以接受輸入并返回一個(gè) React element t(通常是通過 JSX ,它被轉(zhuǎn)化成一個(gè) createElement 調(diào)用)。
有關(guān)更多信息,請查看 React Elements vs React Components
什么時(shí)候在功能組件( Class Component )上使用類組件( Functional Component )?如果您的組件具有狀態(tài)( state )或生命周期方法,請使用 Class 組件。否則,使用功能組件
什么是 React 的 refs ,為什么它們很重要?refs 就像是一個(gè)逃生艙口,允許您直接訪問DOM元素或組件實(shí)例。為了使用它們,您可以向組件添加一個(gè) ref 屬性,該屬性的值是一個(gè)回調(diào)函數(shù),它將接收底層的 DOM 元素或組件的已掛接實(shí)例,作為其第一個(gè)參數(shù)。
class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return () } }
以上注意到我們的輸入字段有一個(gè) ref 屬性,其值是一個(gè)函數(shù)。該函數(shù)接收我們?nèi)缓蠓旁趯?shí)例上的實(shí)際的 DOM 元素,以便在 handleSubmit 函數(shù)內(nèi)部訪問它。經(jīng)常誤解的是,您需要使用類組件才能使用ref ,但 ref 也可以通過利用 JavaScript 中的閉包與 功能組件( functional components )一起使用。
function CustomForm ({handleSubmit}) { let inputElement return () } React 中的 keys 是什么,為什么它們很重要?
keys 是什么幫助 React 跟蹤哪些項(xiàng)目已更改、添加或從列表中刪除。
return (
每個(gè)keys 在兄弟元素之間是獨(dú)一無二的。我們已經(jīng)談過幾次關(guān)于和解(reconciliation)的過程,而且這個(gè)和解過程(reconciliation)中的一部分正在執(zhí)行一個(gè)新的元素樹與最前一個(gè)的差異。keys 使處理列表時(shí)更加高效,因?yàn)?React 可以使用子元素上的 keys 快速知道元素是新的還是在比較樹時(shí)才被移動(dòng)。
而且 keys 不僅使這個(gè)過程更有效率,而且沒有keys,React 不知道哪個(gè)本地狀態(tài)對應(yīng)于移動(dòng)中的哪個(gè)項(xiàng)目。所以當(dāng)你 map 的時(shí)候,不要忽略了 keys 。
看下面的代碼: 如果您在{(user) => user === null ? : }
import React, { Component, PropTypes } from "react" import fetchUser from "twitter" // fetchUser接收用戶名返回 promise // 當(dāng)?shù)玫?用戶的數(shù)據(jù)的時(shí)候 ,返回resolve 狀態(tài) class Twitter extends Component { // 在這里寫下你的代碼 }
如果你不熟悉渲染回調(diào)模式(render callback pattern),這將看起來有點(diǎn)奇怪。在這種模式中,一個(gè)組件接收一個(gè)函數(shù)作為它的 child。注意上面包含在
以下是我的答案。
import React, { Component, PropTypes } from "react" import fetchUser from "twitter" class Twitter extends Component { state = { user: null, } static propTypes = { username: PropTypes.string.isRequired, } componentDidMount () { fetchUser(this.props.username) .then((user) => this.setState({user})) } render () { return this.props.children(this.state.user) } }
值得注意的是,正如我上面提到的,我通過調(diào)用它并傳遞給 user 來把 props.children 處理為為一個(gè)函數(shù)。
這種模式的好處是我們已經(jīng)將我們的父組件與我們的子組件分離了。父組件管理狀態(tài),父組件的消費(fèi)者可以決定以何種方式將從父級(jí)接收的參數(shù)應(yīng)用于他們的 UI。
為了演示這一點(diǎn),我們假設(shè)在另一個(gè)文件中,我們要渲染一個(gè) Profile 而不是一個(gè) Badge,,因?yàn)槲覀兪褂娩秩净卣{(diào)模式,所以我們可以輕松地交換 UI ,而不用改變我們對父(Twitter)組件的實(shí)現(xiàn)。
受控組件( controlled component )與不受控制的組件( uncontrolled component )有什么區(qū)別?{(user) => user === null ? : }
React 的很大一部分是這樣的想法,即組件負(fù)責(zé)控制和管理自己的狀態(tài)。
當(dāng)我們將 native HTML 表單元素( input, select, textarea 等)投入到組合中時(shí)會(huì)發(fā)生什么?我們是否應(yīng)該使用 React 作為“單一的真理來源”,就像我們習(xí)慣使用React一樣? 或者我們是否允許表單數(shù)據(jù)存在 DOM 中,就像我們習(xí)慣使用HTML表單元素一樣? 這兩個(gè)問題是受控(controlled) VS 不受控制(uncontrolled)組件的核心。
受控組件是React控制的組件,也是表單數(shù)據(jù)的唯一真理來源。
如下所示,username 不存在于 DOM 中,而是以我們的組件狀態(tài)存在。每當(dāng)我們想要更新 username 時(shí),我們就像以前一樣調(diào)用setState。
class ControlledForm extends Component { state = { username: "" } updateUsername = (e) => { this.setState({ username: e.target.value, }) } handleSubmit = () => {} render () { return () } }
不受控制( uncontrolled component )的組件是您的表單數(shù)據(jù)由 DOM 處理,而不是您的 React 組件。
我們使用 refs 來完成這個(gè)。
class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return () } }
雖然不受控制的組件通常更容易實(shí)現(xiàn),因?yàn)槟恍枋褂靡脧腄OM獲取值,但是通常建議您通過不受控制的組件來支持受控組件。
主要原因是受控組件支持即時(shí)字段驗(yàn)證,允許您有條件地禁用/啟用按鈕,強(qiáng)制輸入格式,并且更多的是 『the React way』。
在哪個(gè)生命周期事件中你會(huì)發(fā)出 AJAX 請求,為什么?AJAX 請求應(yīng)該在 componentDidMount 生命周期事件中。 有幾個(gè)原因:
Fiber,是下一次實(shí)施React的和解算法,將有能力根據(jù)需要啟動(dòng)和停止渲染,以獲得性能優(yōu)勢。其中一個(gè)取舍之一是 componentWillMount,而在其他的生命周期事件中出發(fā) AJAX 請求,將是具有 “非確定性的”。 這意味著 React 可以在需要時(shí)感覺到不同的時(shí)間開始調(diào)用 componentWillMount。這顯然是AJAX請求的不好的方式。
-您不能保證在組件掛載之前,AJAX請求將無法 resolve。如果這樣做,那意味著你會(huì)嘗試在一個(gè)未掛載的組件上設(shè)置 StState,這不僅不會(huì)起作用,反而會(huì)對你大喊大叫。 在 componentDidMount 中執(zhí)行 AJAX 將保證至少有一個(gè)要更新的組件。
shouldComponentUpdate 應(yīng)該做什么,為什么它很重要?上面我們討論了 reconciliation ,什么是 React 在 setState 被調(diào)用時(shí)所做的。在生命周期方法 shouldComponentUpdate 中,允許我們選擇退出某些組件(和他們的子組件)的 reconciliation 過程。
我們?yōu)槭裁匆@樣做?
如上所述,“和解( reconciliation )的最終目標(biāo)是以最有效的方式,根據(jù)新的狀態(tài)更新用戶界面”。如果我們知道我們的用戶界面(UI)的某一部分不會(huì)改變,那么沒有理由讓 React 很麻煩地試圖去弄清楚它是否應(yīng)該渲染。通過從 shouldComponentUpdate 返回 false,React 將假定當(dāng)前組件及其所有子組件將保持與當(dāng)前組件相同。
您如何告訴React 構(gòu)建(build)生產(chǎn)模式,該做什么?通常,您將使用Webpack的 DefinePlugin 方法將 NODE_ENV 設(shè)置為 production。這將剝離像 propType 驗(yàn)證和額外的警告。除此之外,還有一個(gè)好主意,可以減少你的代碼,因?yàn)镽eact使用 Uglify 的 dead-code 來消除開發(fā)代碼和注釋,這將大大減少你的包的大小。
為什么要使用 React.Children.map(props.children,()=>) 而不是 props.children.map(()=>)因?yàn)椴荒鼙WCprops.children將是一個(gè)數(shù)組。
以此代碼為例,
Welcome.
在父組件內(nèi)部,如果我們嘗試使用 props.children.map 映射孩子,則會(huì)拋出錯(cuò)誤,因?yàn)?props.children 是一個(gè)對象,而不是一個(gè)數(shù)組。
如果有多個(gè)子元素,React 只會(huì)使props.children成為一個(gè)數(shù)組。就像下面這樣:
Welcome.
props.children will now be an array
這就是為什么你喜歡 React.Children.map,因?yàn)樗膶?shí)現(xiàn)考慮到 props.children 可能是一個(gè)數(shù)組或一個(gè)對象。
描述事件在React中的處理方式。為了解決跨瀏覽器兼容性問題,您的 React 中的事件處理程序?qū)鬟fSyntheticEvent 的實(shí)例,它是 React 的瀏覽器本機(jī)事件的跨瀏覽器包裝器。
這些 SyntheticEvent 與您習(xí)慣的原生事件具有相同的接口,除了它們在所有瀏覽器中都兼容。有趣的是,React 實(shí)際上并沒有將事件附加到子節(jié)點(diǎn)本身。React 將使用單個(gè)事件監(jiān)聽器監(jiān)聽頂層的所有事件。這對于性能是有好處的,這也意味著在更新DOM時(shí),React 不需要擔(dān)心跟蹤事件監(jiān)聽器。
createElement 和 cloneElement 有什么區(qū)別?createElement 是 JSX 被轉(zhuǎn)載到的,是 React 用來創(chuàng)建 React Elements 的內(nèi)容(一些 UI 的對象表示)cloneElement用于克隆元素并傳遞新的 props。他們釘住了這兩個(gè)?的命名。
可以選擇性地傳遞給 setState 的第二個(gè)參數(shù)是什么,它的目的是什么?一個(gè)回調(diào)函數(shù),當(dāng)setState結(jié)束并re-rendered該組件時(shí)將被調(diào)用。一些沒有說出來的東西是 setState 是異步的,這就是為什么它需要一個(gè)第二個(gè)回調(diào)函數(shù)。通常最好使用另一個(gè)生命周期方法,而不是依賴這個(gè)回調(diào)函數(shù),但是很高興知道它存在。
this.setState( { username: "tylermcginnis33" }, () => console.log("setState has finished and the component has re-rendered.") )這段代碼有什么問題?
this.setState((prevState, props) => { return { streak: prevState.streak + props.count } })
沒毛病。但是這種寫法很少被使用,并不是眾所周知的,就是你也可以傳遞一個(gè)函數(shù)給setState,它接收到先前的狀態(tài)和道具并返回一個(gè)新的狀態(tài),正如我們在上面所做的那樣。它不僅沒有什么問題,而且如果您根據(jù)以前的狀態(tài)(state)設(shè)置狀態(tài),推薦使用這種寫法。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82411.html
摘要:雖然有著各種各樣的不同,但是相同的是,他們前端優(yōu)化不完全指南前端掘金篇幅可能有點(diǎn)長,我想先聊一聊閱讀的方式,我希望你閱讀的時(shí)候,能夠把我當(dāng)作你的競爭對手,你的夢想是超越我。 如何提升頁面渲染效率 - 前端 - 掘金Web頁面的性能 我們每天都會(huì)瀏覽很多的Web頁面,使用很多基于Web的應(yīng)用。這些站點(diǎn)看起來既不一樣,用途也都各有不同,有在線視頻,Social Media,新聞,郵件客戶端...
摘要:寫在最前本次分享一下在作者上一次失利即拿到畢業(yè)證第二天突然收到阿里社招面試通知失敗之后,通過分析自己的定位與實(shí)際情況,做出的未來一到兩年的規(guī)劃。在博客有一定曝光度的積累中,陸續(xù)收到了一些面試邀請,基本上是阿里的但是我知道我菜。。 寫在最前 本次分享一下在作者上一次失利即拿到畢業(yè)證第二天突然收到阿里社招面試通知失敗之后,通過分析自己的定位與實(shí)際情況,做出的未來一到兩年的規(guī)劃。以及本次社招...
摘要:面試官比較著急了,跟我溝通的時(shí)候,我才知道返回值不一定非要跟原生的一樣。騰訊一面平常開發(fā)怎么設(shè)計(jì)組件的。總結(jié)騰訊面試的感覺就是,沒有那么正式,都是部門的技術(shù)直接聯(lián)系的你,然后二面就是部門負(fù)責(zé)人了,決定了是否入職。 引入 面試過去了這么久,把八月份面試題和總結(jié)發(fā)一下吧,雖然年底大家可能都不換工作~ 還是可以看看的。 關(guān)于面試,引用葉老濕的一句話。你的簡歷是自己工作的答卷,項(xiàng)目經(jīng)歷是你給面...
摘要:的暑期實(shí)習(xí)面試到現(xiàn)在差不多都結(jié)束了,算下來自己也投了十幾家簡歷,經(jīng)歷的差不多十場筆試,現(xiàn)場和電話面試也差不多有五六家公司。阿里三面三面不知道是不是交叉面,不過這次面試面試官說他是北京的之前都是杭州。 2017的暑期實(shí)習(xí)面試到現(xiàn)在差不多都結(jié)束了,算下來自己也投了十幾家簡歷,經(jīng)歷的差不多十場筆試,現(xiàn)場和電話面試也差不多有五六家公司。雖然最后只拿到兩個(gè)offer,所幸是自己期待的公司,下面從...
閱讀 2555·2023-04-26 00:56
閱讀 2009·2021-10-25 09:46
閱讀 1242·2019-10-29 15:13
閱讀 818·2019-08-30 15:54
閱讀 2199·2019-08-29 17:10
閱讀 2619·2019-08-29 15:43
閱讀 503·2019-08-29 15:28
閱讀 3031·2019-08-29 13:24