在React中,如果父组件“ A”重新渲染并更改其子组件“ B”的位置,但B的属性和状态未更改,那么“ B”会重新渲染吗?如果可以,那为什么有必要?
答案 0 :(得分:1)
我尝试给出一个答案,并举例说明我在说什么。不过,您可能还需要等待其他人给出其他答案。
简短的故事:是的,子组件将被重新渲染,这是因为,作为要重新渲染的组件的子组件,其render()
方法将被调用,原因是“瀑布效应”:render()
方法中的每个Component都可以看作一个函数,因此,如果调用render()
方法,则其内部的所有函数都会被再次调用,从而导致重新渲染。
但是,重要的是,即使子组件被重新渲染,这也不意味着DOM会改变!实际上,这不会发生,这是由于React对帐:https://reactjs.org/docs/reconciliation.html。
基本上,React足够聪明,可以查看DOM中是否有更改,并替换实际需要更改的DOM元素(这确实很简单)。
现在,关于示例,请看这个小提琴:
class Child extends React.Component {
/* Un-commeting this function, you can see that the render() method is not called agian.
shouldComponentUpdate(nextProps, nextState) {
if (JSON.stringify(nextProps) === JSON.stringify(this.props) &&
JSON.stringify(nextState) === JSON.stringify(this.state)) {
return false;
}
return true;
}*/
render() {
console.log("Child's rendering");
return (
<p>Child says "Hello World"</p>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {show: false};
}
render() {
return (
<div>
<button onClick={() => this.setState({show: !this.state.show})}>Toggle</button>
{this.state.show && <p>Parent says: Hello World!</p>}
<Child />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
@import url(https://fonts.googleapis.com/css?family=Montserrat);
body {
font-family: 'Montserrat', sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>
每次单击按钮时,控制台中都会显示一条消息Child's rendering
,因此Child
组件正在运行其render()
方法。
但是!如果检查DOM,则在单击按钮时,屏幕上会显示消息“父母说:Hello World”,这就是DOM中发生的情况:
如您所见,DOM中只有带有消息的<p>
元素正在更改!!
在这种情况下,父<div>
元素正在更改,并且仅在更改,这是因为我们已删除其子元素之一。
答案 1 :(得分:0)
这是必要的因为我们正在使用JavaScript,所以我们可以更改子代。我们可以向它们发送特殊属性,确定是否要渲染它们,并通常按照我们的意愿进行操纵。
如果不想每次更新React's PureComponent
时都更新Child Component
,则可以使用Parent Component
您可以使用shouldComponentUpdate来防止重新呈现子组件。它可以用于防止在细粒度的级别呈现组件:
您可以将相等性检查应用于不同的道具和状态,也可以将其用于其他类型的检查。但是,假设您不希望自己检查每个传入的道具,这也很容易出错,而只是在组件的任何相关内容(道具,状态)未发生变化时才防止重新渲染。在这里,您可以使用更广泛但更简单的解决方案来防止重新呈现:React’s PureComponent
。
import React, { Component, PureComponent } from 'react';
...
class Square extends PureComponent {
render() {
return <Item>{this.props.number * this.props.number}</Item>;
}
}
React的PureComponent对组件的道具和状态进行了浅浅的比较。如果什么都没有改变,它将阻止组件的重新呈现。如果发生更改,它将重新提供组件。