Merry Xmas
Before
Portals是React v16特别有价值的更新, 它的出现打破了父组件-子组件这种传统模式, 让你在任意DOM节点下操作组件变得简单.
Example
Antd的Modal: 当你打开DeveloperTools你会发现modal所在的节点并非是在#root下,而是和#root平级生成的新的Dom. 在v16之前你要做这件事并不容易, 起码你要这样写, 借助rc-util/lib/Portal来创建, 但是v16来了, 你只需要ReactDOM.createPortal(child, container)这样.
Journey
代码放到了这里.
这是一个最简单Modal, 点击button,会在button下展现一个Modal, 点击Modal上的Hidebutton会隐藏掉Modal.
点击后效果
可以明显的看到在和root平级地方多出了一个<div>, 这就是刚刚点击button通过portal创建的modal.
Core Code
import React from 'react';import ReactDOM from 'react-dom';
class Modal extends React.Component { constructor(props) { super(props); this.el = document.createElement('div'); } componentDidMount() { document.body.appendChild(this.el); } componentWillUnmount() { document.body.removeChild(this.el); } render() { return ReactDOM.createPortal(this.props.children, this.el); }}
export default Modal;class App extends Component { constructor(props) { super(props); this.state = { style: {}, modalVisible: false, }; this.showModal = this.showModal.bind(this); } showModal() { const dimensions = this.el.getBoundingClientRect(); const left = dimensions.left; const top = dimensions.top + dimensions.height + 10; const height = 200; const width = 200; const style = { left, top, height, width }; this.setState({ style, modalVisible: true, }); } render() { const modal = this.state.modalVisible && ( <Modal> <div className="modal" style={this.state.style}> <p>Hello, World!</p> <button onClick={() => this.setState({ modalVisible: false })}> Hide </button> </div> </Modal> ); return ( <div className="App"> { modal } <button ref={el => this.el = el} onClick={this.showModal}> Show </button> </div> ); }}.modal { background-color: rgba(0,0,0,0.5); position: fixed; height: 100%; width: 100%; top: 0; left: 0; display: flex; align-items: center; justify-content: center; flex-direction: column;}- Modal是一个正常的rederable react component.
- 通过
ReactDOM.createPortal(this.props.children, this.el);在document.body下创建一个<div>,并将其子组件加进去. - 生命周期结束(
componentWillUnmount)将<div>移除. - 在
App.js中, 借助render方法,将Modal加进去, 可以放在<div className="App">下面任意位置,无影响(要保证不出错). - 通过ref获得button的宽高及上下左右位置,设置modal的位置.
After
https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202
这一篇文章, 大佬不光将modal建立在root之外, 更是建立在整个窗体之外.
可以在codepen中体验下.
0 条评论
- 最新
- 最热
- 最早
- 作者
关闭评论
「此时无声胜有声」