React系列——封装一个Portal可复用组件

前端之家收集整理的这篇文章主要介绍了React系列——封装一个Portal可复用组件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Portal简介

使用了React16+的你,对Portal至少有所了解或者熟练使用。
Portal可以创建一个在你的root元素之外的DOM。
1、通常你的网站只有一个root

  1. <body>
  2. <div id="root"></div>
  3. </body>

2、使用Portal之后,可以变成下面这样

  1. <body>
  2. <div id="root"></div>
  3. <div id="portal"></div>
  4. </body>

Portal高阶组件封装

Portal的demo在官网上可以看到,而我们要实现的是将它封装成一个可以复用的组件。

目标

不需要手动在body下面增加HTML,通过组件自己去创建。

  1. <CreatePortal
  2. id,//可以传入id
  3. className,//可以传入className
  4. style //可以传入style
  5. >
  6. 此处插入div或者react组件
  7. </CreatePortal>

实现方案

1、创建一个createPortal函数,该函数将会return一个Portal组件

  1. function createPortal() {
  2.  
  3. }
  4. export default createPortal()

2、创建Portal组件

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import PropTypes from 'prop-types'
  4. function createPortal() {
  5. class Portal extends React.Component{
  6. }
  7. return Portal
  8. }
  9. export default createPortal()

3、render函数实现,用createPortal创建portal。

  1. render() {
  2. return ReactDOM.createPortal(
  3. this.props.children,this.el
  4. )
  5. }

4、componentDidMount函数实现,将dom添加到body下面

  1. componentDidMount() {
  2. document.body.appendChild(this.el);
  3. }

5、componentWillUnmount函数实现,清除DOM结构

  1. componentWillUnmount() {
  2. document.body.removeChild(this.el)
  3. }

6、实现props,包括id、className、style

  1. constructor(props) {
  2. super(props)
  3. this.el = document.createElement('div')
  4. if (!!props) {
  5. this.el.id = props.id || false
  6. if (props.className) this.el.className = props.className
  7. if (props.style) {
  8. Object.keys(props.style).map((v) => {
  9. this.el.style[v] = props.style[v]
  10. })
  11. }
  12. document.body.appendChild(this.el)
  13. }
  14. }

7、完整代码

  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. import PropTypes from 'prop-types'
  4.  
  5. function createPortal() {
  6. class Portal extends React.Component{
  7. constructor(props) {
  8. super(props)
  9. this.el = document.createElement('div')
  10. if (!!props) {
  11. this.el.id = props.id || false
  12. if (props.className) this.el.className = props.className
  13. if (props.style) {
  14. Object.keys(props.style).map((v) => {
  15. this.el.style[v] = props.style[v]
  16. })
  17. }
  18. document.body.appendChild(this.el)
  19. }
  20. }
  21. componentDidMount() {
  22. document.body.appendChild(this.el);
  23. }
  24. componentWillUnmount() {
  25. document.body.removeChild(this.el)
  26. }
  27. render() {
  28. return ReactDOM.createPortal(
  29. this.props.children,this.el
  30. )
  31. }
  32. }
  33. Portal.propTypes = {
  34. style: PropTypes.object
  35. }
  36. return Portal
  37. }
  38. export default createPortal()

总结

createPortal和Provide实现思想类似,用函数式编程的思想来完成目标。如果你觉得这东西有用,拿去用吧。

猜你在找的React相关文章