偶然看到一道react面试题,a组件在b组件内,c组件在a组件内,如何让他渲染出来,a组件和c组件同级。一想,原理应该和Dialog的实现差不多,不过太久没用那个组件已经有点不记得了,而且随着react16的出现也有了更好的解决方式,所以记录一下。
老办法
首先利用老办法,使用unstable_renderSubtreeIntoContainer这个不稳定api来实现。
// App.jsx
class App extends Component {
render() {
return (
<B>
<A><C></C></A>
</B>
);
}
}
// B组件
export default class B extends Component {
render() {
return (
<div>
b组件
<div>
{this.props.children}
</div>
</div>
);
}
}
// C.jsx
export default class C extends Component {
render() {
return (
<div>c组件</div>
);
}
}
B组件和C组件都没什么特别的,主要实现都在A组件
// A组件
export default class A extends Component {
componentDidMount() {
this.parentElement = ReactDOM.findDOMNode(this).parentElement;
this.renderChild();
}
componentDidUpdate() {
this.renderChild();
}
renderChild() {
const renderACom = (
<div>
{this.render()}
{this.props.children}
</div>
)
ReactDOM.unstable_renderSubtreeIntoContainer(
this, renderACom, this.parentElement
);
}
render() {
return <div>a组件</div>;
}
}
这样就能实现这样的效果。
新办法
在react16中新添了createPortal,只用改动一下A组件
export default class A extends Component {
componentDidMount() {
this.forceUpdate();
}
render() {
const renderACom = (
<div>
<div>a组件</div>
{this.props.children}
</div>
)
if (!ReactDOM.findDOMNode(this)) {
return <div></div>;
}
return ReactDOM.createPortal(
renderACom, ReactDOM.findDOMNode(this).parentElement
);
}
}