React Portal 实战——登陆弹窗

React Portal 实战——登陆弹窗

实现效果:

点击初始界面登录按钮,跳转到登录路径,用 Portal 创建一个登录弹窗以及灰色蒙版背景。
要求:

  1. 同时保证原始界面内容保留并显示在蒙版后。
  2. 点击退出按钮后,重定向到“个人档案”页面。

效果图:

登陆界面代码

直接解读代码内容
重点:

  1. 使用 Portal 需要在组件开头导入 ReactDOM.createPortal() 方法,即 import { createPortal } from 'react-dom'
  2. 掌握 Portal 的组织结构:创建DOM节点,添加JSX元素,在组件销毁前移除DOM节点
  3. React Router 重定向
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import React, { Component } from 'react';
import { createPortal } from 'react-dom'
import "../index.css"
import registerPng from '../images/register.png'
//AntDesign调用
import "antd/dist/antd.css"
import { Input, Button } from 'antd'
import { EyeInvisibleOutlined, EyeTwoTone } from '@ant-design/icons';

class Register extends Component {
constructor(props) {
super(props);
this.state = {
isRender: true,
}
this.redirect = this.redirect.bind(this)

const dom = window.document;
this.node = dom.createElement("div")
this.node.setAttribute("id", "account") //this.node.id = "account"
dom.body.appendChild(this.node)
}

redirect() {
// 多余步骤,跳转时其实已经执行了componentWillUnmount;
// 此处只做关于组件销毁的常用方法记录;
this.setState({
isRender: true,
})
this.props.history.push("/person/齐天大圣")
}

componentWillUnmount() {
window.document.body.removeChild(this.node)
}

render() {
return createPortal(
this.state.isRender ? (
<div>
<div className="beijing">
<div className="dengLu">
<img
src={registerPng}
style={{
borderRadius: "15px 15px 0 0",
margin: 0,
padding: 0,
}}
/>
<div className="inputContainer">
<h3 style={{ marginLeft: "40px" }}>账户</h3>
<Input
placeholder="Please enter account..."
className="inputStyle"
style={{
width: "70%",
height: "30px",
marginRight: "40px"
}}
/>
</div>
<div className="inputContainer">
<h3 style={{ marginLeft: "40px" }}>密码</h3>
<Input.Password
placeholder="input password"
iconRender={visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />)}
style={{
width: "70%",
height: "30px",
marginRight: "40px"
}}
/>
</div>
<div className="confirmAction">
<Button>确认</Button>
<Button onClick={this.redirect}>取消</Button>
</div>
</div>
</div>
</div>
) : null
, this.node
)
}
}

export default Register;

代码详解

  1. React v16 Portal 创建的调用方法
    1
    import { createPortal } from 'react-dom'
  2. Portal 主体
    constructor()构造函数中创建DOM节点
    (给DOM节点添加id属性)
    将DOM节点添加到<body>
    createPortal方法创建 Portal,传入可渲染子元素以及挂载的DOM节点,并在render中返回
    componentWillUnmount中,即组件销毁(路由跳转,display:none等都算将组建销毁)前,移除该DOM节点
    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
    class Register extends Component {
    constructor(props) {
    ...
    //创建dom节点
    const dom = window.document;
    this.node = dom.createElement("div")
    this.node.setAttribute("id", "account") //this.node.id = "account"
    dom.body.appendChild(this.node)
    }

    componentWillUnmount() {
    window.document.body.removeChild(this.node)
    }

    render() {
    return createPortal(
    (
    <div>
    ...
    </div>
    )
    , this.node
    )
    }
    }
    export default Register;
  3. React Router 路由重定向
    路由重定向可以实现路由路径的直接跳转,例如进入某一组件,在碰到重定向后自动跳转到另一组件。
    路由重定向可以分为:标签式重定向编程式重定向
    详细参考 Router 路由文章,此处用了编程式的重定向方法this.props.history.push("url")
    1
    2
    3
    4
    5
    6
    7
    8
    redirect() {
    // 多余步骤,跳转时其实已经执行了componentWillUnmount;
    // 此处只做关于组件销毁的常用方法记录;
    this.setState({
    isRender: true,
    })
    this.props.history.push("/person/齐天大圣")
    }

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!