假设我们有一个SidebarLayout
组件,可呈现以下HTML:
<div id="sidebar-layout">
<div id="sidebar"></div>
<div id="content"></div>
</div>
要添加侧边栏内容,我可以轻松地传递另一个组件作为道具,例如:
<SidebarLayout sidebarContent={() => (<SomeOtherComponent />)}>
...
</SidebarLayout>
,然后为render
提供SidebarLayout
函数,如下所示:
class SidebarLayout extends React.Component {
...
render() {
const { sidebarContent: SidebarContent } = this.props;
return (
<div id="sidebar-layout">
<div id="sidebar">
{SidebarContent &&
<SidebarContent />
}
</div>
<div id="content" />
</div>
)
}
}
到目前为止,这就是我们的工作方式。但是,React 16引入了Portal,使我们可以在其原始React树之外渲染组件,典型示例通常以模式,弹出窗口等形式给出。
门户还使它们也可以用于将元素放置在自己的父对象中。这意味着使用以下代码可以实现与上述完全相同的结果(省略了不太重要的代码):
class SidebarLayout extends React.Component {
...
render() {
return (
<div id="sidebar-layout">
<div id="sidebar" />
<div id="content" />
</div>
)
}
}
class SidebarContentPortal extends React.Component {
portalId = "sidebar";
constructor(props) {
super(props);
this.el = document.createElement("div");
}
componentDidMount() {
const contentBar = document.getElementById(this.portalId);
contentBar.appendChild(this.el);
}
componentWillUnmount() {
const contentBar = document.getElementById(this.portalId);
contentBar.removeChild(this.el);
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el
);
}
}
现在我们将SidebarContentPortal
用作:
<SidebarLayout>
...
<SidebarContentPortal>
...
</SidebarContentPortal>
</SidebarLayout>
我想知道以这种确切的方式使用门户网站是否有缺点或弊端,而不是在引入门户网站之前将组件作为道具来传递?