TL;DR => Portals 和 Context 解决不同的目的,一个是在任何级别注入 DOM,另一个是在任何级别注入 props。 Context 可以模仿 Portals 但 Portals 目前无法模仿 Context,至少在没有引入代码异味的情况下是这样。
注意:以下是基于我对这两个概念的理解,如果有人对此有进一步的想法或更正,请随时编辑答案。
据我所知,Portals 顾名思义,是一种用于渲染不需要在组件树层次结构中的组件的途径。这对于Modals、Popovers 或任何需要在树中特定位置缝合的组件非常有效。
Context 用于与各种兄弟组件和子组件进行通信,而无需从父组件一直向下传递道具到预期组件。当然,这是一个重要的功能,但它仍处于实验阶段,可能是因为这可以通过event-emitters 和Redux、MobX 实现集中状态管理。
我假设您的 i18n 用例需要跨组件进行大量通信,您可能希望查看这篇精彩的文章
COMPONENT COMMUNICATION
门户和上下文有助于实现这种通信,但存在差异。 Portals 可以在任何级别渲染或注入 DOM,而 Context 可以在子组件树中的任何级别注入 props。
您总是可以使用Context 实现Portals 能够做到的事情,但我不认为Portals 可以模仿Context 的功能。
EG: 可以使用Context 来模仿Portals 所做的事情。在 PortalsAFAIK 中,您只能发送 DOM 节点 ReactDOM.createPortal(child, container)。可能有办法实现该功能,但这肯定会导致代码异味。
class Parent extends React.Component {
getChildContext() {
return {
renderModal: this.renderModal
}
}
renderModal = (children) => {
this.setState({
open: !this.state.open,
injectableChildren: children
})
}
render() {
this.state.open
?
<div>
{this.state.injectableChildren}
</div>
:
null
// JSX
}
}
class SomeSibling extends React.Component {
static contextTypes = {
renderModal: React.PropTypes.func
}
handleOnClick = (event) => {
this.context.renderModal(renderableChildJSX);
}
renderableChildJSX = () => (
<div>
YAY I AM GETTING RENDERED AT THE ROOT
</div>
)
render() {
return(
<div onClick={this.handleOnClick}>
</div>
)
}
}
就我而言,我害怕使用Context,尽管它很灵活,因为React 文档总是提到它是一个实验性功能,并反复警告不要全面使用此功能。我的猜测是,React 正在考虑稳定此功能或将其完全从 React 代码库中删除,这可能是双向的风险。
结论: IMO,Portals 处于当前状态,它试图解决的问题与 Context 的用途完全不同,最好将 event-emitters 与Context 可能被弃用的唯一原因。