• React-router 将弹框Modal嵌入路由(create a modal route with react-router)


     背景:

      在使用react-router时,我们往往只有在真实的需要页面跳转时,才会将页面加入路由(Route)。对于弹框(Modal),却总是会忽视它的路由需求。

      在开发者眼中: 弹框只是页面中的附属,无需单独准备路由存放。当然,也有其他原因,比如我们想要一个公用的方法,以此来显示弹框。诸如此类,导致开发时没有正视弹框。

      可在用户眼中: 弹框也是页面,至少在想要返回的时候,移除弹框即可(不要把弹框下的页面也给返回了)。

      因此,Modal弹框Route路由BackPress物理返回 三者间的微妙关系就变得尤为关键了

    目的:

      用户视角: 弹框显示时,物理返回(手机返回操作、浏览器左上角回退按钮),只隐藏弹框(不影响下层页面内容,比如滚动、比如输入框内容)

      开发者视角: 1. 原本的目的很简单,只需要在有弹框显示时,物理返回隐藏弹框的同时阻止下层页面的返回

            2. 将弹框加入路由,弹框即页面,会被路由同等对待

    几次尝试:

      1. 使用 popstate 监听

    window.addEventListener("popstate", () => {});

      2. 使用history.listen监听

    history.listen((newLocation, action) => {
        if(action === "PUSH) {
    
        } else {
            // 判断是否存在弹框
            if(ReactDOM.findDOMNode(document.getElementById("modal"))) {
                // 隐藏弹框
           // 前进一个路由 history.go(1) } } })

    注意: 以上方法均是通过监听路由变化(popstate监听、history.listen监听),并辅以判断弹框的显示与否来确定。

    此处使用的是history.go(1)前进一个路由,因为无法阻止在物理返回时的路由回退,只能通过  回退 - 判断有弹框 - 前进 的流程进行

    将Modal加进路由的尝试:

    方式一: 使用 <Route path="/" /> + this.props.location.search改变路由
    - 特点: 通过跳转路由,在原有url上增加"?login=true",PUSH路由,以此判断识别是否显示指定内容
    //  - Router.js中使用: 
        <BrowserRouter>
            <Switch>
                ...
            </Switch>
            <Route path="/" component={Login}>
        </BrowserRouter>
    
    //  - 显示Modal(跳转Login路由):
        <Linl to={{pathname: this.props.match.url, search: "?login=true"}}>To Login</Link>
    
    //  - Login.js中使用
        render() {
            let params = new URLSearchParams(this.props.location.search);
            return(
                params.get("login") && (<Modal>...</Modal>)
            )
        } 
    方式二: 在需要页面增加<Route>节点 + path={this.props.match.url + "/modal"} + React.createPortal(<div>...</div>, #modal_root) + index.html中的 <div id="modal_root"></div>
    - 特点: 在需要的页面增加<Route>节点,且Route的path为当前url(即this.props.match.url) + "/modal",另外Route的渲染内容(render)和通过React.createPortal和外部index.html的<div id="modal_root"></div>关联
    //  - 需要显示Modal的 profile.js
        <Link to={this.props.match.url + "/modal"}>Show Modal</Link>
    
        <Route
            path={this.props.match.url + "/modal"}
            render={() => {
                return (
                    <Modal onClick={() => this.props.history.goBack()}>
                        ...
                    </Modal>
                )
            }}
        />
      
    //  - Modal.js 内容:
        render() {
            return React.createPortal(
                <div onClick={this.props.onClick}>
                    ...
                </div>
            )
        }

    最终使用的方法

     1. 使用路由跳转(本处使用的search),但是仅仅跳转,路由中没有实际内容;
        2. 原本的Modal显示不变方式;
        3. 在Modal的show()方法中,增加history.push({pathname: this.props.match.url, search: "?modal=true"});
        4. 增加 history.listen监听,判断带有相应search的路由回退,即可关闭想要Modal;
        5. 在Modal的hide()方法中,增加history.go(-1),在Modal隐藏时,回退路由。

    引用:

    title: Create a Modal Route with React Router

    author: Jason Brown

    url: https://codedaily.io/tutorials/77/Create-a-Modal-Route-with-React-Router

    github: https://github.com/codedailyio/ReactRouterModal

  • 相关阅读:
    System.Web.Mvc.HttpPostAttribute vs System.Web.Http.HttpPostAttribute? [duplicate]
    Autofac Exception Summary Autofac异常汇总
    AppBox v1.0 发布了
    [原创]ExtAspNet秘密花园(十一) — 布局概述
    ExtAspNet v3.1.9
    ExtAspNet v3.1.8 发布了
    ExtAspNet 主题赏析 7款 超炫!
    ExtAspNet v3.1.7
    ExtAspNet v3.1.6
    [原创]采用Asp.Net的Forms身份验证时,持久Cookie的过期时间会自动扩展
  • 原文地址:https://www.cnblogs.com/nangezi/p/13629241.html
Copyright © 2020-2023  润新知