博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
react Portals(插槽)
阅读量:4101 次
发布时间:2019-05-25

本文共 3578 字,大约阅读时间需要 11 分钟。

这篇文章说说关于Protals2个点:

  • Portals的概念及使用
  • Protals的事件冒泡

一、关于reactPortal插槽。根据官网的说法:

Portal提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

一个 portal 的典型用例是当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框。就是这种需要在某个组件中使用,但是视图上需要在全局的范围。

先来看下Portal的用法:第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

ReactDOM.createPortal(child, container) // child即子组件中的内容,如`
test
<
`组件中的`
test
`

由于是在我现有测试项目的基础上改造,所以和官网例子稍微有点不同。不过是可以对照着看的:

App.js

//  这是app根组件,Routers渲染home页。也就是说,我们即将要渲染的弹窗会在id为`box`的`div`中。和渲染出的home平级。import Routers from './router/router';class App extends Component {
render () {
return (
) }}export default App;

home.js

/* eslint-disable */import React from "react";import Header from '../../component/header/header.js';import Footer from '../../component/footer/footer';import Sidebar from '../../component/sidebar/sidebar';import './home.scss'const modalRoot = document.getElementById('box');   // 获取`id`为`box`的`dom`// 弹窗组件class Modal extends React.Component {
constructor(props) {
super(props); this.el = document.createElement('div'); } componentDidMount() {
modalRoot.appendChild(this.el); } componentWillUnmount() {
modalRoot.removeChild(this.el); } render() {
return ReactDOM.createPortal( this.props.children, this.el, ); } }// 父组件class Home extends Component {
constructor(props) {
super(props) this.state = {
showModal: false, } } handleShow = () => {
this.setState({
showModal: true, }) } handleHide = () => {
this.setState({
showModal: false, }) } getModal = () => {
console.log('这是Modal冒泡的事件') } render () {
const modal = this.state.showModal ? (
With a portal, we can render content into a different part of the DOM, as if it were any other React child.
This is being rendered inside the #modal-container div.
) : null; return (
This div has overflow: hidden.
{
modal}
) }}export default Home

home.scss

.app {
height: 10em; width: 10em; background: lightblue; overflow: hidden;} .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;}

代码逻辑: 在App根组件,放置了一个id为boxdom,同级放置了一个渲染home页面的Router组件。在home组件中渲染modal

此时,modalhome组件的子节点。当showModalfalse的时候,不进行渲染。为true时,渲染Modal组件。Modal组件先是创建了一个div并且插入到id为boxdiv中。利用ReactDOM.createPortalModal中的节点渲染到创建的div中。

渲染结果

在这里插入图片描述
下面是注释掉modalRoot.removeChild(this.el);
在这里插入图片描述

这里Modal组件最终渲染在父组件Home之外的App组件id为box的dom上。

建议:项目中实际使用时,可以将Modal单独写一个文件。直接引用就可以。最大限度的复用可以降低冗余。
代码中Modal组件,在componentDidMountcomponentWillUnmount中分别添加和移除了dom。可以试一下,如果不移除,那么每渲染一次Modal节点中就会多出一对div节点。这样不符合我们优化的思想。

二、Protals事件冒泡。上面的代码在Home组件下classNameapp的dom上添加了getModal事件。这时候我们运行程序,点击Hide modal按钮,打开控制台,会发现打印出这是Modal冒泡的事件。虽然Modal最终是挂载到box下面。但从Modal中冒泡上来的事件依然能被{modal}的所有parents捕捉到。

转载地址:http://xnzsi.baihongyu.com/

你可能感兴趣的文章
db db2_monitorTool IBM Rational Performace Tester
查看>>
postgresql监控工具pgstatspack的安装及使用
查看>>
【JAVA数据结构】双向链表
查看>>
【JAVA数据结构】先进先出队列
查看>>
谈谈加密和混淆吧[转]
查看>>
乘法逆元
查看>>
Objective-C 基础入门(一)
查看>>
通过mavlink实现自主航线的过程笔记
查看>>
Flutter Boost的router管理
查看>>
iOS开发支付集成之微信支付
查看>>
Koa2框架原理解析和实现
查看>>
C++模板
查看>>
【C#】如何实现一个迭代器
查看>>
【C#】利用Conditional属性完成编译忽略
查看>>
hbase(1)---概述
查看>>
hbase(5)---API示例
查看>>
SSM-CRUD(1)---环境搭建
查看>>
Nginx(2)---安装与启动
查看>>
springBoot(5)---整合servlet、Filter、Listener
查看>>
C++ 模板类型参数
查看>>