Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/414.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应门户解决了什么问题?_Javascript_Reactjs_Modal Dialog - Fatal编程技术网

Javascript 反应门户解决了什么问题?

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

从react门户的文档中:

门户的一个典型用例是父组件具有溢出:隐藏或z索引样式,但您需要子组件从其容器中可视化地“脱离”。例如,对话框、悬停卡和工具提示

建议的解决方案是使用:

// 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捕获未捕获的冒泡事件。


我想问一下答案。但我知道用户f
ixed
将其定位为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>