React面试题整理
<h2 id="react面试题整理">React面试题整理</h2><h3 id="1react的生命周期">1、react的生命周期</h3>
<h4 id="1生命周期是什么">1)、生命周期是什么?</h4>
<p>react 实例的生命周期,就是react实例从初始化,更新,到销毁的过程</p>
<h4 id="2react实例生命周期经历三个阶段">2)、react实例生命周期经历三个阶段</h4>
<p> 初始化阶段:完成从react组件创建到首次渲染的过程</p>
<p> 更新阶段:当调用setState函数时,会引起组件的重新渲染</p>
<p> 销毁阶段:完成组件的销毁</p>
<h4 id="3三个阶段分别对应的构造函数有">3)、三个阶段分别对应的构造函数有:</h4>
<ul>
<li><strong>初始化阶段:</strong><br>
<strong>constructor</strong></li>
</ul>
<p> 构造函数里,可以做状态的初始化,接收props的传值</p>
<p> componentWillMount: 在渲染前调用,相当于vue中的beforeMount</p>
<p><strong>render</strong></p>
<pre><code class="language-javascript"> 渲染函数,不要在这里修改数据。 vue中也有render函数。
</code></pre>
<p><strong>componentDidMount</strong></p>
<p> 渲染完毕,在第一次渲染后调用。</p>
<ul>
<li><strong>运行中阶段(更新)</strong><br>
当组件的 props 或 state 发生变化时会触发更新<strong>(严谨的说,是只要调用了setState()或者改变了props时)</strong>。组件更新的生命周期调用顺序如下:</li>
</ul>
<p><strong> shouldComponentUpdate</strong></p>
<p> 是否更新? 需要返回true或者false。如果是false,那么组件就不会继续更新了。</p>
<p> <strong>componentWillUpdate,</strong></p>
<p> 即将更新。</p>
<p> <strong>componentWillReceiveProps(nextProps)</strong>: 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。nextProps 是props的新值,而 this.props是旧值。</p>
<p> <strong>render</strong></p>
<p> 不要在这里修改数据</p>
<p> <strong>componentDidUpdate</strong></p>
<p> 在组件完成更新后立即调用。在初始化时不会被调用。 相当于vue中的updated</p>
<ul>
<li><strong>销毁阶段(卸载)</strong></li>
</ul>
<p><strong>componentWillUnmount()</strong></p>
<p>即将卸载,可以做一些组件相关的清理工作,例如取消计时器、网络请求等</p>
<h4 id="2为什么虚拟dom-会提高性能">2、为什么虚拟DOM 会提高性能</h4>
<p> 首先,(虚拟DOM是什么) 虚拟DOM就是一个JavaScript对象。通过这个JavaScript对象来描述真实DOM</p>
<p> 如:</p>
<pre><code class="language-javascript">{
tagName:"p",
style:"width:200px;height: 100px;",
innerHTML:"我是p"
},
</code></pre>
<p>其次,操作虚拟DOM,就是在操作javascript对象,所以,并不会引起页面的重绘和重排。而操作真实DOM是会引起页面的重绘和重排的。</p>
<p> https://blog.csdn.net/jiang7701037/article/details/98516468 (页面的重排和回流)</p>
<h3 id="3react的diff原理">3、React的diff原理</h3>
<ul>
<li>
<p><strong>传统diff算法</strong><br>
需要遍历整棵树的节点然后进行比较,是一个深度递归的过程,运算复杂度常常是O(n^3)</p>
</li>
<li>
<p><strong>react diff的优化策略</strong></p>
</li>
<li>
<p>DOM节点跨层级的操作不做优化,因为很少这么做,这是针对的tree层级的策略;</p>
</li>
<li>
<p>对于同一个类的组件,会生成相似的树形结构,对于不同类的组件,生成不同的树形结构,这是针对conponent层级的策略;</p>
</li>
<li>
<p>对于同一级的子节点,拥有同层唯一的key值,来做删除、插入、移动的操作,这是针对element层级的策略;</p>
</li>
</ul>
<h3 id="4调用setstate之后发生了什么">4、调用setState之后,发生了什么?</h3>
<p> 1)、合并state</p>
<p> 把传入setState()里的参数对象和当前的state进行(属性)合并。 触发调和过程(Reconciliation)</p>
<p> 2)、 重新渲染组件</p>
<p> 2.1) React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面;</p>
<p> 2.2) React 会自动计算出新的树与老树的节点差异(用diff算法),然后根据差异对界面进行最小化重渲染</p>
<p></p>
<h3 id="5state和props的区别">5、state和props的区别</h3>
<p> 1)、state是组件的状态,也叫组件内部的数据</p>
<p> 2)、props是组件的属性,也可以认为是外部给组件传入的数据</p>
<p></p>
<h3 id="6在构造函数里调用super函数并把props作为参数传入的作用是啥">6、在构造函数里调用super函数并把props作为参数传入的作用是啥?</h3>
<p> 1)、在构造函数里调用super的目的是:保证子类(组件里)有this;</p>
<p> 在ES6中,super()函数就是父类的构造函数。所以,在react里定义类组件时,调用super就是在调用React.Component的构造函数。</p>
<p> 2)、调用super函数时,把props传入的目的是,保证this有属性props;即:在子类(组件)里能够使用this.props。</p>
<p> 即: 执行 super(props) 是为了让 React.Component 初始化 this.props。</p>
<p>React.Component类内部写法:</p>
<pre><code class="language-javascript">class Component {
constructor(props) {
this.props = props;
}
}
</code></pre>
<p> 3)、补充解释:</p>
<p> 看代码(很奇怪的现象):</p>
<pre><code class="language-javascript">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"))
</code></pre>
<blockquote>
<p>为什么会出现以上情况?</p>
</blockquote>
<p>因为,React组件(如:上面的Home组件)在实例化时, 会设置一遍 props 。所以,没有问题喽。</p>
<p>那,那,那……??@#¥……&!*…… 天哪?</p>
<p>再看:</p>
<pre><code class="language-javascript">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"))
</code></pre>
<p>所以:</p>
<p>组件的super里如果不传递props</p>
<p>1)、可以在其它函数里使用this.props,因为,组件的构造函数会再次设置props的</p>
<p>2)、在构造函数里,this.props是undefined。即:this.props.属性名会报错。因为,React.Component的构造函数没有增加props属性。</p>
<h3 id="7为什么建议传递给setstate函数的参数是回调函数而不是对象">7、为什么建议传递给setState函数的参数是回调函数而不是对象?</h3>
<p>因为,this.setState()函数内部是异步执行的。</p>
<p>1)、如果给setState()的参数写成对象的话,你会误以为它是同步的。进而,如果想使用新的值,就会下意识调用setState完毕后,直接使用新的msg的值,</p>
<p>如下代码,你是否会下意识(“直观”)地觉得是异步呢,哈哈</p>
<pre><code class="language-javascript">this.setState({
msg:"hello"
});
console.log(this.state.msg);// 亲,这个值不是hello
</code></pre>
<p>2)、如果写成回调函数的话,你就不会有以上的误解。</p>
<p>如下代码:</p>
<pre><code class="language-javascript">//改变状态前后都想做一些事情:
this.setState((prevState)=>{
// prevState:是旧值
console.log("prevState",prevState)
return {
age:15
}
},()=>{
// this.state:就是新值。
console.log(this.state.age);
});
</code></pre>
<h3 id="8react中的setstate是同步执行还是异步执行如果是异步的怎么拿到执行后的state">8、React中的setState是同步执行还是异步执行?如果是异步的?怎么拿到执行后的state?</h3>
<p>setState是异步的。</p>
<p>如果要拿到修改后的状态,需要使用回调函数的方式,如下:</p>
<pre><code class="language-javascript">//改变状态后想做一些事情:
this.setState({
属性名:属性值
}, () => {
//一般是用于在setState之后做一些操作
//this.state == 修改之后的state
})
</code></pre>
<h3 id="9为什么不能直接用以下办法更新state">9、为什么不能直接用以下办法更新state</h3>
<p> this.state.msg = “hello”;</p>
<p> 因为,这样不会引起组件的重新渲染,所以,数据修改后没法 呈现在页面上。</p>
<p> 而调用setState()函数,会引起组件的重新渲染,这样更新的数据就会呈现在页面上。</p><br><br>
来源:https://www.cnblogs.com/tuxiaotu/p/15662340.html
頁:
[1]