我会发布你的上下文代码:
class Application extends React.Component {
render() {
return (
<div>
{/*
Clicking this component only logs
the parents render function
*/}
<DynamicParent>
<Child />
</DynamicParent>
{/*
Clicking this component logs both the
parents and child render functions
*/}
<StaticParent />
</div>
);
}
}
class DynamicParent extends React.Component {
state = { x: false };
render() {
console.log("DynamicParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
{this.props.children}
</div>
);
}
}
class StaticParent extends React.Component {
state = { x: false };
render() {
console.log("StaticParent");
return (
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
);
}
}
function Child(props) {
console.log("child");
return <div>Child Text</div>;
}
当您在应用程序渲染中编写此代码时:
<StaticParent />
渲染的是这样的:
<div onClick={() => this.setState({ x: !this.state.x })}>
<Child />
</div>
实际上,发生的事情(大致)是这样的:
function StaticParent(props) {
return React.createElement(
"div",
{ onClick: () => this.setState({ x: !this.state.x }) },
React.createElement(Child, null)
);
}
React.createElement(StaticParent, null);
当你像这样渲染你的 DynamicParent 时:
<DynamicParent>
<Child />
</DynamicParent>
这就是实际发生的事情(再次粗略地说)
function DynamicParent(props) {
return React.createElement(
"div",
{
onClick: () => this.setState({ x: !this.state.x }),
children: props.children
}
);
}
React.createElement(
DynamicParent,
{ children: React.createElement(Child, null) },
);
在这两种情况下,这都是孩子:
function Child(props) {
return React.createElement("div", props, "Child Text");
}
这是什么意思?好吧,在您的 StaticParent 组件中,每次调用 StaticParent 的渲染方法时,您都会调用 React.createElement(Child, null)。在 DynamicParent 案例中, Child 被创建一次并作为道具传递。而且由于React.createElement 是一个纯函数,所以它可能为了性能而被记忆在某个地方。
在 DynamicParent 的情况下让 Child 的渲染再次运行的原因是 Child 的 props 发生了变化。例如,如果父级的状态被用作子级的道具,那么在这两种情况下都会触发重新渲染。
我真的希望丹·阿布拉莫夫不要出现在 cmets 上来破坏这个答案,写起来很痛苦(但很有趣)