React教程之封装一个Portal可复用组件的方法


Posted in Javascript onJanuary 02, 2018

Portal简介

所以我们需要的一个通用组件,它做如下的事情:

  • 可以声明式的写在一个组件中
  • 并不真正render在被声明的地方
  • 支持过渡动画

那么,像modal、tooltip、notification等组件都是可以基于这个组件的。我们叫这个组件为Portal。

使用了React16+的你,对Portal至少有所了解或者熟练使用。

Portal可以创建一个在你的root元素之外的DOM。

1、通常你的网站只有一个root

<body>
 <div id="root"></div>
</body>

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

<body>
 <div id="root"></div>
 <div id="portal"></div>
</body>

Portal高阶组件封装

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

目标

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

<CreatePortal
 id, //可以传入id
 className, //可以传入className
 style //可以传入style
 >
 此处插入div或者react组件
</CreatePortal>

实现方案

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

function createPortal() {

}
export default createPortal()

2、创建Portal组件

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
function createPortal() {
 class Portal extends React.Component{
 }
 return Portal
}
export default createPortal()

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

render() {
 return ReactDOM.createPortal(
  this.props.children,
  this.el
 )
}

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

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

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

componentWillUnmount() {
   document.body.removeChild(this.el)
  }

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

constructor(props) {
 super(props)
 this.el = document.createElement('div')
 if (!!props) {
  this.el.id = props.id || false
  if (props.className) this.el.className = props.className
  if (props.style) {
   Object.keys(props.style).map((v) => {
    this.el.style[v] = props.style[v]
   })
  }
  document.body.appendChild(this.el)
 }
}

7、完整代码

import React from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'
function createPortal() {
 class Portal extends React.Component{
  constructor(props) {
   super(props)
   this.el = document.createElement('div')
   if (!!props) {
    this.el.id = props.id || false
    if (props.className) this.el.className = props.className
    if (props.style) {
     Object.keys(props.style).map((v) => {
      this.el.style[v] = props.style[v]
     })
    }
    document.body.appendChild(this.el)
   }
  }
  componentDidMount() {
   document.body.appendChild(this.el);
  }
  componentWillUnmount() {
   document.body.removeChild(this.el)
  }
  render() {
   return ReactDOM.createPortal(
    this.props.children,
    this.el
   )
  }
 }
 Portal.propTypes = {
  style: PropTypes.object
 }
 return Portal
}
export default createPortal()

总结

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

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jquery 3D球状导航的文章分类
Jul 06 Javascript
jquery中的过滤操作详细解析
Dec 02 Javascript
jquery插件splitScren实现页面分屏切换模板特效
Jun 16 Javascript
JS日期加减,日期运算代码
Nov 05 Javascript
JS 通过系统时间限定动态添加 select option的实例代码
Jun 09 Javascript
同步异步动态引入js文件的几种方法总结
Sep 23 Javascript
JavaScript实现一个带AI的井字棋游戏源码
May 21 Javascript
详解封装基础的angular4的request请求方法
Jun 05 Javascript
详解基于DllPlugin和DllReferencePlugin的webpack构建优化
Jun 28 Javascript
详解vue项目中使用token的身份验证的简单实践
Mar 08 Javascript
Vue+ElementUI 中级联选择器Bug问题的解决
Jul 31 Javascript
JavaScript流程控制(分支)
Dec 06 Javascript
Node层模拟实现multipart表单的文件上传示例
Jan 02 #Javascript
10行原生JS实现文字无缝滚动(超简单)
Jan 02 #Javascript
js原生实现移动端手指滑动轮播图效果的示例
Jan 02 #Javascript
vue父组件向子组件(props)传递数据的方法
Jan 02 #Javascript
基于wordpress的ajax写法详解
Jan 02 #Javascript
基于Vue的SPA动态修改页面title的方法(推荐)
Jan 02 #Javascript
jq.ajax+php+mysql实现关键字模糊查询(示例讲解)
Jan 02 #Javascript
You might like
mod_php、FastCGI、PHP-FPM等PHP运行方式对比
2015/07/02 PHP
PHP入门教程之使用Mysqli操作数据库的方法(连接,查询,事务回滚等)
2016/09/11 PHP
PHP实现的Redis多库选择功能单例类
2017/07/27 PHP
javascript 播放器 控制
2007/01/22 Javascript
jquery按回车提交数据的代码示例
2013/11/05 Javascript
JS对象转换为Jquery对象示例
2014/01/26 Javascript
jQuery中animate用法实例分析
2015/03/09 Javascript
代码分析jQuery四种静态方法使用
2015/07/23 Javascript
JS中dom0级事件和dom2级事件的区别介绍
2016/05/05 Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
2016/06/09 Javascript
好好了解一下Cookie(强烈推荐)
2016/06/14 Javascript
Angular2 环境配置详细介绍
2016/09/21 Javascript
js判断iframe中元素是否存在的实现代码
2016/12/24 Javascript
Angular 5.x 学习笔记之Router(路由)应用
2018/04/08 Javascript
浅谈vue中关于checkbox数据绑定v-model指令的个人理解
2018/11/14 Javascript
通过微信公众平台获取公众号文章的方法示例
2019/12/25 Javascript
微信小程序实现聊天室
2020/08/21 Javascript
vue 全局封装loading加载教程(全局监听)
2020/11/05 Javascript
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
[01:34]DOTA2 7.22版本新增神杖效果一览(敏捷英雄篇)
2019/05/28 DOTA
Python实现测试磁盘性能的方法
2015/03/12 Python
Python读取Word(.docx)正文信息的方法
2018/03/15 Python
python3+PyQt5实现自定义窗口部件Counters
2018/04/20 Python
解决python中遇到字典里key值为None的情况,取不出来的问题
2018/10/17 Python
python3转换code128条形码的方法
2019/04/17 Python
解决Python对齐文本字符串问题
2019/08/28 Python
Pytorch之卷积层的使用详解
2019/12/31 Python
html5基础标签(html5视频标签 html5新标签用法)
2013/12/30 HTML / CSS
庆祝教师节活动方案
2014/01/31 职场文书
2014年维稳工作总结
2014/11/18 职场文书
二年级语文上册复习计划
2015/01/19 职场文书
工程技术负责人岗位职责
2015/04/13 职场文书
少年雷锋观后感
2015/06/10 职场文书
解决SpringCloud Feign传对象参数调用失败的问题
2021/06/23 Java/Android
MySQL query_cache_type 参数与使用详解
2021/07/01 MySQL
Ubuntu安装Mysql+启用远程连接的完整过程
2022/06/21 Servers