React实现优雅的弹窗

Posted 一杯清泉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React实现优雅的弹窗相关的知识,希望对你有一定的参考价值。

        实现弹窗的原理关键在于,如何将弹窗组件挂载到任意的dom上,参考weui.js,提供了思路,可以通过append将元素添加到指定的父节点上,来实现弹窗的显示,隐藏的时候在移除该元素即可,如下示例:

参考:https://github.com/Tencent/weui.js/blob/master/src/picker/picker.js

        在react同样可以使用该思路来实现,弹窗的显示和隐藏。但是在react中一般不这么搞,因为react已经提供了相关的API来实现,分别是unstable_renderSubtreeIntoContainer和Portal组件,其中unstable_renderSubtreeIntoContainer已经过去,被Portal替代,原因是unstable_renderSubtreeIntoContainer使用起来麻烦,而且换不稳定,主要表现在以下两点:

1、需要自己管理组件的生命周期,用React.render()渲染到某个DOM节点,如果要卸载的话需要手动执行unmountComponentAtNode()

2、接受不到Context的值。用render()渲染的组件是无法获取到上级节点的Context值的。比如多语言机制实现。

        下面主要介绍Portals的两种弹窗的用法:

一、静态弹窗

        静态弹窗是初始化渲染的时候要加载的内容已经被渲染到指定的节点里面,隐藏和显示通过变量控制。

1、dialog

import React, useEffect, useState from 'react';
import ReactDOM from 'react-dom'

export default function Dialog(props) 
    const [node, setNode] = useState();

    useEffect(() => 
        const element = document.createElement('div');
        document.body.appendChild(element);
        setNode(element);
        return () => 
            document.body.removeChild(element);
        ;
    , []);

    return node ? ReactDOM.createPortal(props.children, node) : null;

2、App

import React, useState from 'react'
import Dialog from "./dialog";

export default function App() 
    const [show, isShow] = useState(false)
    return (
        <div>
            <button onClick=() => 
                isShow(show=> !show)
            >点击显示
            </button>
            show && <Dialog>
                <div>
                    我是一个简答的弹窗
                </div>
            </Dialog>
        </div>
    );

二、动态弹窗

        动态弹窗是初始化渲染的时候要加载的内容没有被渲染到指定的节点里面,需要显示的时候再加载,隐藏和显示单独控制。

1、dialog同上

2、App

import React from 'react'
import ReactDOM from 'react-dom'
import Dialog from "./dialog";

export default function App() 
    const div = document.createElement('div');
    return (
        <div>
            <button onClick=() => 
                ReactDOM.render(
                    <Dialog>
                        我是一个弹窗
                    </Dialog>,
                    div
                );
            >点击显示
            </button>
            <button onClick=() => 
                const unmountResult = ReactDOM.unmountComponentAtNode(div);
                if (unmountResult && div.parentNode) 
                    div.parentNode.removeChild(div);
                
            >点击隐藏
            </button>
        </div>
    );

三、效果图

 参考文档:

https://zhuanlan.zhihu.com/p/52016989

https://react.docschina.org/docs/portals.html

以上是关于React实现优雅的弹窗的主要内容,如果未能解决你的问题,请参考以下文章

react中antd每当打开不一样的弹窗时,不能更新弹窗的内容

一款基于react-native的弹窗提示组件

ViewModel优雅的弹加载窗和获取Context

React实现单例组件

Kotlin 实现从顶部带TextView(点击取消)的弹窗的功能

JAVA的弹窗怎么做?