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
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
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
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
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
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
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
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
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
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