在 React 项目中使用路由的形式打开弹框

轩陌

分类: React 169 0

前言

由于之前一直都是在使用 Vue 做项目,遇见的弹框基本都是通过显示隐藏实现的弹框,最近开始在做 React 项目,发现一种新的模式,在 React 里面可以通过路由的形式打开弹框,也比较好奇具体怎么实现的,在一些特定的场景下路由的形式会比一般通过显示隐藏来的更方便,比如前端是使用的微前端模式,各个模块的前端都是完全独立的,如果想在一个模块打开另一个模块的某个弹框,在使用显示与隐藏的形式需要找到组件的记录的状态然后在去更改,首先是组件的状态不好拿到,也不好维护,如果通过路由的形式打开弹框,即可轻松解决这个问题,只需要在这个模块跳转路由即可,路由打开还有个方便之处可以很方便的解决刷新之后弹框依旧需要展示的问题。

实现原理

在 React 里面,一切皆组件。
举例:一共有 home、about 两个页面,共三个组件,页面 home 对应组件 Home,页面 about 对应 About 组件,弹框则对应 Dialog 组件,弹框是在 home 页面打开,home 页面的路径为 /,弹框的路径为 /dialog,about 页面路径为 /about,react-router 在不加精准匹配 exact 的模式下是可以匹配到多个组件的,核心就是使用这个模式完成,一个页面也是组件,如果按照上边的举例,当我们在浏览器输入 /dialog 一共会匹配到两个组件,即 Home、Dialog,效果如下:

具体实现

由于 class 组件比较重,我这里使用函数组件实现,具体实现需要用到 react-routerReactDOM.createPortal

ReactDOM.createPortal 用法摘自官网:https://zh-hans.reactjs.org/docs/portals.html
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。意思就是可以将一个 React 组件渲染到页面已有的元素内。
具体语法:ReactDOM.createPortal(child, container),第一个参数是一个 React.Node,第二个是需要将节点渲染到哪里的具体容器。

  1. 第一步准备一个弹框组件,使用 position: fixed 将弹框定位在页面的最上层,通过 ReactDOM.createPortal 将组件渲染到 body,外层通过 Route 组件将弹框包裹起来,组件接收两个 props,分别为 pathonClose,并在调用地址设置一个路径,这里示例使用 /dialog 作为弹框组件的路径。

    path 用于弹框组件的路由,即 react-router 路径参数
    onClose 用于接收弹框关闭的事件

    具体代码如下:

    
    // 弹框组件
    function Dialog(props) {
      const history = useHistory()
    
      // 渲染弹框内容
      function DialogContent() {
        return <div className="dialog-content">{props.children}</div>;
      }
    
      // 弹框关闭事件
      function onClose() {
        history.go(-1)
        props?.onClose()
      }
    
      // 将弹框渲染到 body
      return ReactDOM.createPortal(
        <Route path={props.path}>
          <div className="dialog" onClick={onClose}>
            <DialogContent />
          </div>
        </Route>,
        document.body
      )
    }
    
  2. 第二步准备具体渲染页面用的组件,HomeAbout 两个组件,代码如下

    
    function Home() {
      const history = useHistory()
    
      // 点击打开弹框
      function handleShowDialog() {
        history.push('/dialog')
      }
    
      return <>
        <div>Home</div>
        <span style={{ color: '#00f', cursor: 'pointer' }} onClick={handleShowDialog}>Dialog</span>
      </>
    }
    
    function About() {
      return <div>About</div>
    }
    
  3. 第三步准备渲染完整页面的代码

    
    function App() {
      function onClose() {
        console.log('弹框关闭了~')
      }
    
      return (
        <>
          <Link to="/">Home</Link>
          <Link to="/about">About</Link>
          <Switch>
            <Route path="/about">
              <About />
            </Route>
            <Route path="/">
              <Home />
            </Route>
          </Switch>
          <Dialog path="/dialog" onClose={onClose}>我是弹框内容,点我可以关闭啦~</Dialog>
        </>
      );
    }
    

参考资料

源码:https://github.com/D-xuanmo/react-router-dialog

  • 3人 Love
  • 0人 Haha
  • 0人 Wow
  • 1人 Sad
  • 0人 Angry
React、react 路由弹框

作者简介: 轩陌

打赏

生命的意义在于折腾。

共 0 条评论关于 “在 React 项目中使用路由的形式打开弹框”

Loading...