偶然看到一道react面試題,a組件在b組件內(nèi),c組件在a組件內(nèi),如何讓他渲染出來(lái),a組件和c組件同級(jí)。一想,原理應(yīng)該和Dialog的實(shí)現(xiàn)差不多,不過(guò)太久沒(méi)用那個(gè)組件已經(jīng)有點(diǎn)不記得了,而且隨著react16的出現(xiàn)也有了更好的解決方式,所以記錄一下。
老辦法
首先利用老辦法,使用unstable_renderSubtreeIntoContainer這個(gè)不穩(wěn)定api來(lái)實(shí)現(xiàn)。
// 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組件都沒(méi)什么特別的,主要實(shí)現(xiàn)都在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>;
}
}
這樣就能實(shí)現(xiàn)這樣的效果。
新辦法
在react16中新添了createPortal,只用改動(dòng)一下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
);
}
}