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 相关文章推荐
(currentStyle)javascript为何有时用style得不到已设定的CSS的属性
Aug 15 Javascript
ext combox 下拉框不出现自动提示,自动选中的解决方法
Feb 24 Javascript
浅谈jQuery页面的滚动位置scrollTop、scrollLeft
May 19 Javascript
gulp-uglify 与gulp.watch()配合使用时报错(重复压缩问题)
Aug 24 Javascript
vue组件初学_弹射小球(实例讲解)
Sep 06 Javascript
仿京东快报向上滚动的实例
Dec 13 Javascript
在vue中使用css modules替代scroped的方法
Mar 10 Javascript
Vue 应用中结合vux使用微信 jssdk的方法
Aug 28 Javascript
详解微信小程序网络请求接口封装实例
May 02 Javascript
JS中数据结构与算法---排序算法(Sort Algorithm)实例详解
Jun 17 Javascript
对TypeScript库进行单元测试的方法
Jul 18 Javascript
基于layui实现高级搜索(筛选)功能
Jul 26 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
PHP 获取客户端真实IP地址多种方法小结
2010/05/15 PHP
Yii框架日志记录Logging操作示例
2018/07/12 PHP
PHP实现用session来实现记录用户登陆信息
2018/10/15 PHP
PHP implode()函数用法讲解
2019/03/08 PHP
Laravel 实现数据软删除功能
2019/08/21 PHP
javascript下arguments,caller,callee,call,apply示例及理解
2009/12/24 Javascript
jcarousellite.js 基于Jquery的图片无缝滚动插件
2010/12/30 Javascript
JavaScript常用判断写法大全(推荐)
2016/05/30 Javascript
js获取浏览器高度 窗口高度 元素尺寸 偏移属性的方法
2016/11/21 Javascript
select下拉框插件jquery.editable-select详解
2017/01/22 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
2017/03/07 Javascript
Vue+axios 实现http拦截及路由拦截实例
2017/04/25 Javascript
JS判断非空至少输入两个字符的简单实现方法
2017/06/23 Javascript
Vue.Draggable拖拽功能的配置使用方法
2020/07/29 Javascript
Cocos2d实现刮刮卡效果
2018/12/20 Javascript
Layui table field初始化加载时进行隐藏的方法
2019/09/19 Javascript
JS实现移动端双指缩放和旋转方法
2019/12/13 Javascript
vue@cli3项目模板怎么使用public目录下的静态文件
2020/07/07 Javascript
VUE使用axios调用后台API接口的方法
2020/08/03 Javascript
OpenLayers3实现对地图的基本操作
2020/09/28 Javascript
python算法学习之基数排序实例
2013/12/18 Python
Python基于有道实现英汉字典功能
2015/07/25 Python
详解Golang 与python中的字符串反转
2017/07/21 Python
python中使用正则表达式的连接符示例代码
2017/10/10 Python
解决Python print输出不换行没空格的问题
2018/11/14 Python
python 实现将多条曲线画在一幅图上的方法
2019/07/07 Python
Python 静态方法和类方法实例分析
2019/11/21 Python
详解pytorch中squeeze()和unsqueeze()函数介绍
2020/09/03 Python
在Ubuntu中安装并配置Pycharm教程的实现方法
2021/01/06 Python
纯css3显示隐藏一个div特效的具体实现
2014/02/10 HTML / CSS
html5配合css3实现带提示文字的输入框(摆脱js)
2013/03/08 HTML / CSS
北京某科技有限公司C# .net笔试题
2014/09/27 面试题
养牛场项目建议书
2014/05/13 职场文书
2015年社会治安综合治理工作总结
2015/04/10 职场文书
PhpSpreadsheet中文文档 | Spreadsheet操作教程实例
2021/04/01 PHP
Golang 实现获取当前函数名称和文件行号等操作
2021/05/08 Golang