Maoyl's blog Maoyl's blog
首页
  • 前端基础

    • HTML
    • CSS
    • CSS动画
    • JavaScript文章
    • stylus
  • 性能优化

    • 《性能优化》笔记
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《JavaScript设计模式》笔记
    • 《TypeScript 从零实现 axios》
    • TypeScript笔记
    • JS设计模式总结笔记
  • 前端框架

    • Vue相关
    • React相关
  • 前端监控

    • 前端监控简介
  • 学习笔记

    • 《Vue》笔记
    • 《React》笔记
    • 小程序学习笔记
  • 后端基础

    • Nodejs
  • 学习笔记

    • 数据结构
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网页性能
  • 学习笔记

    • 《Git》学习笔记
    • 《Vim》学习笔记
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

maoyln

日日行,不怕千万里
首页
  • 前端基础

    • HTML
    • CSS
    • CSS动画
    • JavaScript文章
    • stylus
  • 性能优化

    • 《性能优化》笔记
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《JavaScript设计模式》笔记
    • 《TypeScript 从零实现 axios》
    • TypeScript笔记
    • JS设计模式总结笔记
  • 前端框架

    • Vue相关
    • React相关
  • 前端监控

    • 前端监控简介
  • 学习笔记

    • 《Vue》笔记
    • 《React》笔记
    • 小程序学习笔记
  • 后端基础

    • Nodejs
  • 学习笔记

    • 数据结构
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • 网页性能
  • 学习笔记

    • 《Git》学习笔记
    • 《Vim》学习笔记
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • React的Portal的用法
    • react Portal语法解释
    • react Portal使用方法
    • createPortal实践
    • Portals事件传递
  • 自适应方案PxToRem
  • 01_30_30React相关
maoyln
2022-03-01
目录

React的Portal的用法

github:https://github.com/maoyln/react-createPortal (opens new window)

# React的Portal的用法

我们思考一个问题,我们创建了一个字组建之后,想要把它放在指定的dom元素下面,有什么办法吗?

# react Portal语法解释

Portals 提供了一个最好的在父组件包含的DOM结构层级外的DOM节点渲染组件的方法

// child可以是ReactElement, Arrays, fragments, Portals, String, numbers,
// Booleans, null, ...
// container是dom元素
ReactDOM.createPortal(child, container);
1
2
3
4
  • 第一个参数child是可渲染的react子项,
  • 第一个参数container是需要挂载到dom元素

# react Portal使用方法

# 引入

import {createPortal} from 'react-dom'
1

# 使用方法

createPortal(
  <div>
    {
      createPortalRender()
    }
  </div>,
  document.getElementById('root')
);
1
2
3
4
5
6
7
8

# 完整代码

// App.js
import React from 'react';
import createPortalDom from './reactPortalDom';
import './App.css';

function App() {
  return (
    <main>
      <h1>createPortal</h1>
      <div className="father" id="father">
        父节点
        {
          createPortalDom()
        }
      </div>
    </main>
  );
}

export default App;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// createPortalDom.js
import React from 'react';
import { createPortal } from 'react-dom';

const createPortalDom = () => {
  const createPortalRender = () => {
    return (
      <div id='children' className="children">
        孩子节点
      </div>
    );
  }
  return (
    createPortal(
      <div>
        {
          createPortalRender()
        }
      </div>,
      document.getElementById('root')
    )
  );
}

export default createPortalDom;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* App.css */
main {
  align-content: center;
  text-align: center;
}
.father {
  border: 1px solid #ff00ff;
  padding: 10px;
  background-color: #cccccc;
}

.children {
  border: 1px solid #0000ff;
  background-color: #ff0000;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# createPortal实践

# 默认dom

// createPortalDom.js
import React from 'react';

const createPortalDom = () => {
  const createPortalRender = () => {
    return (
      <div id='children' className="children">
        孩子节点
      </div>
    );
  }
  return (
    <div>
      {
        createPortalRender()
      }
    </div>
  );
}

export default createPortalDom;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 使用createPortal

// createPortalDom.js
import React from 'react';
import { createPortal } from 'react-dom';

const createPortalDom = () => {
  const createPortalRender = () => {
    return (
      <div id='children' className="children">
        孩子节点
      </div>
    );
  }
  return (
    createPortal(
      <div>
        {
          createPortalRender()
        }
      </div>,
      document.getElementById('root')
    )
  );
}

export default createPortalDom;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#
仔细观察使用`createPortal`前后`dom`节点的变换
使用`createPortal`之前,`children`dom节点在`father`dom节点下
使用`createPortal`之后,`children`dom节点在`root`dom节点下
1
2
3

注意

孩子节点使用createPortal之后,孩子节点文字从居中(继承的父节点样式)样式变成了默认左对齐样式,可以看出createPortal修改dom节点后,有可能影响原有样式,这里建议使用内联样式

# Portals事件传递

import React from 'react';
import { createPortal } from 'react-dom';

const createPortalDom = () => {
  const clickChild = () => {
    console.log('点击孩子节点');
  }
  const createPortalRender = () => {
    return (
      <div onClick={clickChild} id='children' className="children">
        孩子节点
      </div>
    );
  }
  return (
    createPortal(
      <div>
        {
          createPortalRender()
        }
      </div>,
      document.getElementById('root')
    )
  );
}

export default createPortalDom;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

虽然我们通过Dom操作,把它移到了root节点下,与React的虚拟Dom结构不一致,但是React的虚拟Dom结构并未发生变化,父子关系仍然存在。这就导致,事件的传递依然有效,在createPortalDom组件触发的click事件,依然会传递到root节点中。

编辑 (opens new window)
上次更新: 2025/04/18, 01:42:12
自适应方案PxToRem

自适应方案PxToRem→

最近更新
01
GSAP动画库——如何高效写动画
04-17
02
自适应方案PxToRem
09-10
03
性能优化-requestAnimationFrame
08-10
更多文章>
Theme by Vdoing | Copyright © 2019-2025 备案号:京ICP备19058102号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式