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下组织javascript代码(js函数化)
Aug 25 Javascript
JS操作select下拉框动态变动(创建/删除/获取)
Jun 02 Javascript
jquery获取css中的选择器(实例讲解)
Dec 02 Javascript
JavaScript操作Cookie详解
Feb 28 Javascript
js实现用户离开页面前提示是否离开此页面的方法(包括浏览器按钮事件)
Jul 18 Javascript
深入分析javascript中的错误处理机制
Jul 17 Javascript
原生JS实现跑马灯效果
Feb 20 Javascript
Vuex利用state保存新闻数据实例
Jun 28 Javascript
JS实现区分中英文并统计字符个数的方法示例
Jun 09 Javascript
vue返回上一页面时回到原先滚动的位置的方法
Dec 20 Javascript
Vue起步(无cli)的啊教程详解
Apr 11 Javascript
vue中keep-alive内置组件缓存的实例代码
Apr 16 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
mantis安装、配置和使用中的问题小结
2014/07/14 PHP
AppBaseJs 类库 网上常用的javascript函数及其他js类库写的
2010/03/04 Javascript
jQuery EasyUI API 中文文档 搜索框
2011/09/29 Javascript
NodeJS的url截取模块url-extract的使用实例
2013/11/18 NodeJs
使用documentElement正确取得当前可见区域的大小
2014/07/25 Javascript
Javascript对象Clone实例分析
2015/06/09 Javascript
js控制文本框输入的字符类型方法汇总
2015/06/19 Javascript
javascript获取select值的方法分析
2015/07/02 Javascript
JavaScript取得WEB安全颜色列表的方法
2015/07/14 Javascript
3种js实现string的substring方法
2015/11/09 Javascript
简单总结JavaScript中的String字符串类型
2016/05/26 Javascript
jQuery插件实现文件上传功能(支持拖拽)
2020/08/27 Javascript
javascript cookie用法基础教程(概念,设置,读取及删除)
2016/09/20 Javascript
原生js编写2048小游戏
2017/03/17 Javascript
jQuery插件FusionCharts绘制的2D双柱状图效果示例【附demo源码】
2017/05/13 jQuery
vue实现图书管理demo详解
2017/10/17 Javascript
webpack+react+antd脚手架优化的方法
2018/04/02 Javascript
JS事件流与事件处理程序实例分析
2019/08/16 Javascript
[54:54]Newbee vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
python有证书的加密解密实现方法
2014/11/19 Python
使用Kivy将python程序打包为apk文件
2017/07/29 Python
浅谈python下tiff图像的读取和保存方法
2018/12/04 Python
python 获取微信好友列表的方法(微信web)
2019/02/21 Python
python绘制规则网络图形实例
2019/12/09 Python
Python3与fastdfs分布式文件系统如何实现交互
2020/06/23 Python
python爬取天气数据的实例详解
2020/11/20 Python
Python脚本调试工具安装过程
2021/01/11 Python
澳洲本土太阳镜品牌:Quay Australia
2019/07/29 全球购物
MySQL面试题
2014/01/12 面试题
生物化工专业个人自荐信
2013/09/26 职场文书
高一新生军训感言
2014/03/02 职场文书
《海底世界》教学反思
2014/04/16 职场文书
团日活动总结书
2014/05/08 职场文书
老公保证书
2015/01/17 职场文书
2019思想汇报范文
2019/05/21 职场文书
MySQL 查询速度慢的原因
2021/05/25 MySQL