React面試題整理


React面試題整理

1、react的生命周期

1)、生命周期是什么?

react 實例的生命周期,就是react實例從初始化,更新,到銷毀的過程

2)、react實例生命周期經歷三個階段

​ 初始化階段:完成從react組件創建到首次渲染的過程

​ 更新階段:當調用setState函數時,會引起組件的重新渲染

​ 銷毀階段:完成組件的銷毀

3)、三個階段分別對應的構造函數有:

  • 初始化階段:
    constructor

​ 構造函數里,可以做狀態的初始化,接收props的傳值

​ componentWillMount: 在渲染前調用,相當於vue中的beforeMount

​render

 渲染函數,不要在這里修改數據。 vue中也有render函數。

componentDidMount

​ 渲染完畢,在第一次渲染后調用。

  • 運行中階段(更新)
    當組件的 props 或 state 發生變化時會觸發更新(嚴謹的說,是只要調用了setState()或者改變了props時)。組件更新的生命周期調用順序如下:

​ shouldComponentUpdate

​ 是否更新? 需要返回true或者false。如果是false,那么組件就不會繼續更新了。

componentWillUpdate,

​ 即將更新。

componentWillReceiveProps(nextProps): 在組件接收到一個新的 prop (更新后)時被調用。這個方法在初始化render時不會被調用。nextProps 是props的新值,而 this.props是舊值。

render

​ 不要在這里修改數據

componentDidUpdate

​ 在組件完成更新后立即調用。在初始化時不會被調用。 相當於vue中的updated

  • 銷毀階段(卸載)

componentWillUnmount()

即將卸載,可以做一些組件相關的清理工作,例如取消計時器、網絡請求等

2、為什么虛擬DOM 會提高性能

​ 首先,(虛擬DOM是什么) 虛擬DOM就是一個JavaScript對象。通過這個JavaScript對象來描述真實DOM

​ 如:

{
    tagName:"p",
    style:"width:200px;height: 100px;",
    innerHTML:"我是p"
},

其次,操作虛擬DOM,就是在操作javascript對象,所以,並不會引起頁面的重繪和重排。而操作真實DOM是會引起頁面的重繪和重排的。

https://blog.csdn.net/jiang7701037/article/details/98516468 (頁面的重排和回流)

3、React的diff原理

  • 傳統diff算法
    ​ 需要遍歷整棵樹的節點然后進行比較,是一個深度遞歸的過程,運算復雜度常常是O(n^3)

  • react diff的優化策略

  • DOM節點跨層級的操作不做優化,因為很少這么做,這是針對的tree層級的策略;

  • 對於同一個類的組件,會生成相似的樹形結構,對於不同類的組件,生成不同的樹形結構,這是針對conponent層級的策略;

  • 對於同一級的子節點,擁有同層唯一的key值,來做刪除、插入、移動的操作,這是針對element層級的策略;

4、調用setState之后,發生了什么?

​ 1)、合並state

​ 把傳入setState()里的參數對象和當前的state進行(屬性)合並。 觸發調和過程(Reconciliation)

​ 2)、 重新渲染組件

​ 2.1) React 會以相對高效的方式根據新的狀態構建 React 元素樹並且着手重新渲染整個 UI 界面;

​ 2.2) React 會自動計算出新的樹與老樹的節點差異(用diff算法),然后根據差異對界面進行最小化重渲染

5、state和props的區別

​ 1)、state是組件的狀態,也叫組件內部的數據

​ 2)、props是組件的屬性,也可以認為是外部給組件傳入的數據

6、在構造函數里調用super函數並把props作為參數傳入的作用是啥?

​ 1)、在構造函數里調用super的目的是:保證子類(組件里)有this;

​ 在ES6中,super()函數就是父類的構造函數。所以,在react里定義類組件時,調用super就是在調用React.Component的構造函數。

​ 2)、調用super函數時,把props傳入的目的是,保證this有屬性props;即:在子類(組件)里能夠使用this.props。

​ 即: 執行 super(props) 是為了讓 React.Component 初始化 this.props。

React.Component類內部寫法:

class Component {
  constructor(props) {
    this.props = props;
  }
}

​ 3)、補充解釋:

​ 看代碼(很奇怪的現象):

class Home extends React.Component{
    constructor(props){
        super();//此處沒有props
    }
    render(){
        return (
            {/*下面竟然可以拿到 this.props*/}
            <div>{this.props.name}</div>  
        )
    }
}
ReactDOM.render(<Home name="hi"/>,document.getElementById("box"))

為什么會出現以上情況?

因為,React組件(如:上面的Home組件)在實例化時, 會設置一遍 props 。所以,沒有問題嘍。

那,那,那……??@#¥……&!*…… 天哪?

再看:

class Home extends React.Component{
    constructor(props){
        super();//此處沒有props
        console.log(this.props);//這個是undefined。請在super里傳遞props,試試
    }
    render(){
        return (
            <div>{this.props.name}</div>  
        )
    }
}
ReactDOM.render(<Home name="hi"/>,document.getElementById("box"))

所以:

組件的super里如果不傳遞props

1)、可以在其它函數里使用this.props,因為,組件的構造函數會再次設置props的

2)、在構造函數里,this.props是undefined。即:this.props.屬性名會報錯。因為,React.Component的構造函數沒有增加props屬性。

7、為什么建議傳遞給setState函數的參數是回調函數而不是對象?

因為,this.setState()函數內部是異步執行的。

1)、如果給setState()的參數寫成對象的話,你會誤以為它是同步的。進而,如果想使用新的值,就會下意識調用setState完畢后,直接使用新的msg的值,

如下代碼,你是否會下意識(“直觀”)地覺得是異步呢,哈哈

this.setState({
     msg:"hello"
});
console.log(this.state.msg);// 親,這個值不是hello

2)、如果寫成回調函數的話,你就不會有以上的誤解。

如下代碼:

//改變狀態前后都想做一些事情:
this.setState((prevState)=>{
    // prevState:是舊值
    console.log("prevState",prevState)
    return {
        age:15
    }
},()=>{
    // this.state:就是新值。
    console.log(this.state.age);
}); 

8、React中的setState是同步執行還是異步執行?如果是異步的?怎么拿到執行后的state?

setState是異步的。

如果要拿到修改后的狀態,需要使用回調函數的方式,如下:

//改變狀態后想做一些事情:
this.setState({
  屬性名:屬性值
}, () => {
  //一般是用於在setState之后做一些操作
  //this.state == 修改之后的state
})

9、為什么不能直接用以下辦法更新state

​ this.state.msg = “hello”;

​ 因為,這樣不會引起組件的重新渲染,所以,數據修改后沒法 呈現在頁面上。

​ 而調用setState()函數,會引起組件的重新渲染,這樣更新的數據就會呈現在頁面上。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM