Javascript 反应门户解决了什么问题?
从react门户的文档中: 门户的一个典型用例是父组件具有溢出:隐藏或z索引样式,但您需要子组件从其容器中可视化地“脱离”。例如,对话框、悬停卡和工具提示 建议的解决方案是使用:Javascript 反应门户解决了什么问题?,javascript,reactjs,modal-dialog,Javascript,Reactjs,Modal Dialog,从react门户的文档中: 门户的一个典型用例是父组件具有溢出:隐藏或z索引样式,但您需要子组件从其容器中可视化地“脱离”。例如,对话框、悬停卡和工具提示 建议的解决方案是使用: // this line is rendered in `Portal1` component, // which is rendered in `Parent1` component. ReactDOM.createPortal(Child1, Container1) 我不明白它能解决什么问题。为什么使Child
// this line is rendered in `Portal1` component,
// which is rendered in `Parent1` component.
ReactDOM.createPortal(Child1, Container1)
我不明白它能解决什么问题。为什么使
Child1
成为Container1
的子级而不是Parent1
有帮助
我的问题可能不清楚,因此如果它不->此解决方案与创建“对话框、悬停卡和工具提示”的其他解决方案有何不同?在React V15中,我们只能将子dom添加到父dom中。这意味着,如果您想拥有一个元素,必须创建一个新的div。如下所示:
<div>
{this.props.children}
</div>
溢出:隐藏或z索引样式 如果父组件具有溢出:隐藏或z索引样式,并且子元素类型为对话框、鼠标悬停卡、工具提示等,则这些元素应位于父元素的上层,这意味着断开。但它们可能被父组件遮住 所以createPortal提供了一个更好的选择。它可以加载到父组件的上部组件上。在将元素装载到另一个dom后,它将不会受到保护
事件与泡沫
即使是安装在另一个组件上的组件,事件也可能出现在父组件上。当您初始化React应用程序时,
ReactDOM
告诉一个DOM
容器,它的所有React组件都将在此DOM
下呈现。这使得React可以执行所有渲染处理
有时,您需要控制React组件作为子元素呈现给不同的DOM
元素,并继续与React应用程序交互。这就是我们使用React门户的原因
由于React在引擎盖下创建虚拟元素,因此无法将转换为DOM
元素并将其直接插入DOM
。React门户允许您传递React元素并为React元素指定容器DOM
以下是一个例子:
您有一个Modal
组件,它在中心呈现一个div
元素
function Modal() {
return (
<div style={{ position: 'absolute', left: '50%'}}>
Message
</div>
);
}
问题是,当呈现模态
组件时,其位置相对于父级div
的位置,但您需要将其显示在窗口的中心
为了解决此问题,您可以使用门户将模态
组件直接附加到主体
元素
以下是门户的解决方案
function ModalRenderer() {
return (
React.createPortal(
<Modal />,
document.body
)
);
}
ModalRenderer
具有用于Modal
的容器元素,该元素位于DOM树之外,但仍位于React应用程序树中一个很好的例子是分离CSS关注点
以下是一个例子:
HTML
巴别塔
请注意,文本居中。模态的工作方式是转到模态根
并将DOM元素附加到那里。您可以在模式根目录下拥有自己的CSS,独立于父组件(应用程序根目录
)
您现在不再有义务将您的“子”组件附加到父组件下。在这种情况下,您(app root
)将其附加到其同级(modal root
)。您可以将其完全附加到document.body
,或任何您想要的元素。另一个好处是,正如其他用户所提到的,事件冒泡的发生就像子组件是他们自己的子组件一样
#app root中的父组件将能够从同级节点#modal root捕获未捕获的冒泡事件。
我想问一下答案。但我知道用户fixed
将其定位为css替代react modals。反应模态的意义是什么?你是指模态
组件?
<div style={{ position: 'relative', left: 100 }}>
<Modal />
</div>
function ModalRenderer() {
return (
React.createPortal(
<Modal />,
document.body
)
);
}
<div style={{ position: 'relative', left: 100 }}>
<ModalRenderer />
</div>
<div id="app-root"></div>
<div id="modal-root"></div>
.app {
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.modal {
background-color: rgba(0,0,0,0.5);
}
const appRoot = document.getElementById('app-root')
const modalRoot = document.getElementById('modal-root')
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
showModal: false
}
this.handleShow = this.handleShow.bind(this);
this.handleHide = this.handleHide.bind(this);
}
handleShow() {
this.setState({
showModal: true
})
}
handleHide() {
this.setState({
showModal: false
})
}
render() {
const modal = this.state.showModal ? (
<Modal>
<div className="modal">I am no longer centered!</div>
</Modal>
) : null
return (
<div className='app'>
Basic
<button onClick={this.handleShow}>
Show Modal
</button>
{modal}
</div>
)
}
}
class Modal extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
}
componentDidMount(){
modalRoot.appendChild(this.el)
}
componentWillUnmount() {
modalRoot.removeChild(this.el)
}
render() {
return ReactDOM.createPortal(
this.props.children,
this.el
)
}
}
ReactDOM.render(<App />, appRoot)
<div className='app'>
Basic
<button onClick={this.handleShow}>
Show Modal
</button>
<div className="modal">I am centered ;(</div>
</div>