常見react面試題彙總(適合中級前端)

已經開源

地址:https://github.com/nanhupatar...
關注咱們團隊:
圖片描述react

React 中 keys 的做用是什麼?

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

render () {
  return (
    <ul>
      {this.state.todoItems.map(({item, key}) => {
        return <li key={key}>{item}</li>
      })}
    </ul>
  )
}

在開發過程當中,咱們須要保證某個元素的 key 在其同級元素中具備惟一性。在 React Diff 算法中 React 會藉助元素的 Key 值來判斷該元素是新近建立的仍是被移動而來的元素,從而減小沒必要要的元素重渲染。此外,React 還須要藉助 Key 值來判斷元素與本地狀態的關聯關係,所以咱們毫不可忽視轉換函數中 Key 的重要性。github

調用 setState 以後發生了什麼?

在代碼中調用 setState 函數以後,React 會將傳入的參數對象與組件當前的狀態合併,而後觸發所謂的調和過程(Reconciliation)。通過調和過程,React 會以相對高效的方式根據新的狀態構建 React 元素樹而且着手從新渲染整個 UI 界面。在 React 獲得元素樹以後,React 會自動計算出新的樹與老樹的節點差別,而後根據差別對界面進行最小化重渲染。在差別計算算法中,React 可以相對精確地知道哪些位置發生了改變以及應該如何改變,這就保證了按需更新,而不是所有從新渲染。算法

react 生命週期函數

  • 初始化階段:redux

    • getDefaultProps:獲取實例的默認屬性
    • getInitialState:獲取每一個實例的初始化狀態
    • componentWillMount:組件即將被裝載、渲染到頁面上
    • render:組件在這裏生成虛擬的 DOM 節點
    • componentDidMount:組件真正在被裝載以後
  • 運行中狀態:promise

    • componentWillReceiveProps:組件將要接收到屬性的時候調用
    • shouldComponentUpdate:組件接受到新屬性或者新狀態的時候(能夠返回 false,接收數據後不更新,阻止 render 調用,後面的函數不會被繼續執行了)
    • componentWillUpdate:組件即將更新不能修改屬性和狀態
    • render:組件從新描繪
    • componentDidUpdate:組件已經更新
  • 銷燬階段:瀏覽器

    • componentWillUnmount:組件即將銷燬

shouldComponentUpdate 是作什麼的,(react 性能優化是哪一個周期函數?)

shouldComponentUpdate 這個方法用來判斷是否須要調用 render 方法從新描繪 dom。由於 dom 的描繪很是消耗性能,若是咱們能在 shouldComponentUpdate 方法中可以寫出更優化的 dom diff 算法,能夠極大的提升性能。緩存

參考react 性能優化-sf安全

爲何虛擬 dom 會提升性能?(必考)

虛擬 dom 至關於在 js 和真實 dom 中間加了一個緩存,利用 dom diff 算法避免了沒有必要的 dom 操做,從而提升性能。性能優化

用 JavaScript 對象結構表示 DOM 樹的結構;而後用這個樹構建一個真正的 DOM 樹,插到文檔當中當狀態變動的時候,從新構造一棵新的對象樹。而後用新的樹和舊的樹進行比較,記錄兩棵樹差別把 2 所記錄的差別應用到步驟 1 所構建的真正的 DOM 樹上,視圖就更新了。

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

react diff 原理(常考,大廠必考)

  • 把樹形結構按照層級分解,只比較同級元素。
  • 給列表結構的每一個單元添加惟一的 key 屬性,方便比較。
  • React 只會匹配相同 class 的 component(這裏面的 class 指的是組件的名字)
  • 合併操做,調用 component 的 setState 方法的時候, React 將其標記爲 dirty.到每個事件循環結束, React 檢查全部標記 dirty 的 component 從新繪製.
  • 選擇性子樹渲染。開發人員能夠重寫 shouldComponentUpdate 提升 diff 的性能。

參考:React 的 diff 算法

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>
  )
}

若是你建立了相似於下面的 Twitter 元素,那麼它相關的類定義是啥樣子的?

<Twitter username='tylermcginnis33'>
  {(user) => user === null
    ? <Loading />
    : <Badge info={user} />}
</Twitter>
import React, { Component, PropTypes } from 'react'
import fetchUser from 'twitter'
// fetchUser take in a username returns a promise
// which will resolve with that username's data.
class Twitter extends Component {
  // finish this
}

若是你還不熟悉回調渲染模式(Render Callback Pattern),這個代碼可能看起來有點怪。這種模式中,組件會接收某個函數做爲其子組件,而後在渲染函數中以 props.children 進行調用:

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)
  }
}

這種模式的優點在於將父組件與子組件解耦和,父組件能夠直接訪問子組件的內部狀態而不須要再經過 Props 傳遞,這樣父組件可以更爲方便地控制子組件展現的 UI 界面。譬如產品經理讓咱們將本來展現的 Badge 替換爲 Profile,咱們能夠輕易地修改下回調函數便可:

<Twitter username='tylermcginnis33'>
  {(user) => user === null
    ? <Loading />
    : <Profile info={user} />}
</Twitter>

展現組件(Presentational component)和容器組件(Container component)之間有何不一樣

  • 展現組件關心組件看起來是什麼。展現專門經過 props 接受數據和回調,而且幾乎不會有自身的狀態,但當展現組件擁有自身的狀態時,一般也只關心 UI 狀態而不是數據的狀態。
  • 容器組件則更關心組件是如何運做的。容器組件會爲展現組件或者其它容器組件提供數據和行爲(behavior),它們會調用 Flux actions,並將其做爲回調提供給展現組件。容器組件常常是有狀態的,由於它們是(其它組件的)數據源。

類組件(Class component)和函數式組件(Functional component)之間有何不一樣

  • 類組件不只容許你使用更多額外的功能,如組件自身的狀態和生命週期鉤子,也能使組件直接訪問 store 並維持狀態
  • 當組件僅是接收 props,並將組件自身渲染到頁面時,該組件就是一個 '無狀態組件(stateless component)',可使用一個純函數來建立這樣的組件。這種組件也被稱爲啞組件(dumb components)或展現組件

(組件的)狀態(state)和屬性(props)之間有何不一樣

  • State 是一種數據結構,用於組件掛載時所需數據的默認值。State 可能會隨着時間的推移而發生突變,但多數時候是做爲用戶事件行爲的結果。
  • Props(properties 的簡寫)則是組件的配置。props 由父組件傳遞給子組件,而且就子組件而言,props 是不可變的(immutable)。組件不能改變自身的 props,可是能夠把其子組件的 props 放在一塊兒(統一管理)。Props 也不只僅是數據--回調函數也能夠經過 props 傳遞。

何爲受控組件(controlled component)

在 HTML 中,相似 <input>, <textarea><select> 這樣的表單元素會維護自身的狀態,並基於用戶的輸入來更新。當用戶提交表單時,前面提到的元素的值將隨表單一塊兒被髮送。但在 React 中會有些不一樣,包含表單元素的組件將會在 state 中追蹤輸入的值,而且每次調用回調函數時,如 onChange 會更新 state,從新渲染組件。一個輸入表單元素,它的值經過 React 的這種方式來控制,這樣的元素就被稱爲"受控元素"。

何爲高階組件(higher order component)

高階組件是一個以組件爲參數並返回一個新組件的函數。HOC 運行你重用代碼、邏輯和引導抽象。最多見的多是 Redux 的 connect 函數。除了簡單分享工具庫和簡單的組合,HOC 最好的方式是共享 React 組件之間的行爲。若是你發現你在不一樣的地方寫了大量代碼來作同一件事時,就應該考慮將代碼重構爲可重用的 HOC。

爲何建議傳遞給 setState 的參數是一個 callback 而不是一個對象

由於 this.props 和 this.state 的更新多是異步的,不能依賴它們的值去計算下一個 state。

除了在構造函數中綁定 this,還有其它方式嗎

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

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

在 super() 被調用以前,子類是不能使用 this 的,在 ES2015 中,子類必須在 constructor 中調用 super()。傳遞 props 給 super() 的緣由則是便於(在子類中)能在 constructor 訪問 this.props。

應該在 React 組件的何處發起 Ajax 請求

在 React 組件中,應該在 componentDidMount 中發起網絡請求。這個方法會在組件第一次「掛載」(被添加到 DOM)時執行,在組件的生命週期中僅會執行一次。更重要的是,你不能保證在組件掛載以前 Ajax 請求已經完成,若是是這樣,也就意味着你將嘗試在一個未掛載的組件上調用 setState,這將不起做用。在 componentDidMount 中發起網絡請求將保證這有一個組件能夠更新了。

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

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

這些 SyntheticEvent 與您習慣的原生事件具備相同的接口,除了它們在全部瀏覽器中都兼容。有趣的是,React 實際上並無將事件附加到子節點自己。React 將使用單個事件監聽器監聽頂層的全部事件。這對於性能是有好處的,這也意味着在更新 DOM 時,React 不須要擔憂跟蹤事件監聽器。

createElement 和 cloneElement 有什麼區別?

React.createElement():JSX 語法就是用 React.createElement()來構建 React 元素的。它接受三個參數,第一個參數能夠是一個標籤名。如 div、span,或者 React 組件。第二個參數爲傳入的屬性。第三個以及以後的參數,皆做爲組件的子組件。

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

React.cloneElement()與 React.createElement()類似,不一樣的是它傳入的第一個參數是一個 React 元素,而不是標籤名或組件。新添加的屬性會併入原有的屬性,傳入到返回的新元素中,而就的子元素獎盃替換。

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

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

React.createClass()、ES6 class 和無狀態函數。

react 組件的劃分業務組件技術組件?

  • 根據組件的職責一般把組件分爲 UI 組件和容器組件。
  • UI 組件負責 UI 的呈現,容器組件負責管理數據和邏輯。
  • 二者經過 React-Redux 提供 connect 方法聯繫起來。

簡述 flux 思想

Flux 的最大特色,就是數據的"單向流動"。

  1. 用戶訪問 View
  2. View 發出用戶的 Action
  3. Dispatcher 收到 Action,要求 Store 進行相應的更新
  4. Store 更新後,發出一個"change"事件
  5. View 收到"change"事件後,更新頁面

React 項目用過什麼腳手架(本題是開放性題目)

creat-react-app Yeoman 等

瞭解 redux 麼,說一下 redux 把

  • redux 是一個應用數據流框架,主要是解決了組件間狀態共享的問題,原理是集中式管理,主要有三個核心方法,action,store,reducer,工做流程是 view 調用 store 的 dispatch 接收 action 傳入 store,reducer 進行 state 操做,view 經過 store 提供的 getState 獲取最新的數據,flux 也是用來進行數據操做的,有四個組成部分 action,dispatch,view,store,工做流程是 view 發出一個 action,派發器接收 action,讓 store 進行數據更新,更新完成之後 store 發出 change,view 接受 change 更新視圖。Redux 和 Flux 很像。主要區別在於 Flux 有多個能夠改變應用狀態的 store,在 Flux 中 dispatcher 被用來傳遞數據到註冊的回調事件,可是在 redux 中只能定義一個可更新狀態的 store,redux 把 store 和 Dispatcher 合併,結構更加簡單清晰
  • 新增 state,對狀態的管理更加明確,經過 redux,流程更加規範了,減小手動編碼量,提升了編碼效率,同時缺點時當數據更新時有時候組件不須要,可是也要從新繪製,有些影響效率。通常狀況下,咱們在構建多交互,多數據流的複雜項目應用時纔會使用它們

redux 有什麼缺點

  • 一個組件所須要的數據,必須由父組件傳過來,而不能像 flux 中直接從 store 取。
  • 當一個組件相關數據更新時,即便父組件不須要用到這個組件,父組件仍是會從新 render,可能會有效率影響,或者須要寫複雜的 shouldComponentUpdate 進行判斷。
相關文章
相關標籤/搜索