React离开路由时确认弹窗

一、离开路由弹出弹窗

最近做一个h5的需求,要求在用户页面返回时如果操作了就弹出一个弹窗,来提示用户是否保存此页面所操作的内容。

之前做过vue的路由守卫,但是react的还是第一次做,就记录一下。

首先需要引入withRouter,来包裹一下需要弹窗的页面,此时在componentDidMount中才能获取到 this.props.route,

因为我们的项目需要弹窗的页面是又通过HOC高阶组件进行了一次嵌套的,所以用withRouter来包装弹窗页面,而componentDidMount中的内容是写在HOC组件中的,这样才能达到效果。

这样就可以在routerWillLeave函数中写一些逻辑来判断是否弹出,nextLocation是接下来要跳转的路由,如果要阻止就return false,否则就return true;

        import { withRouter } from 'react-router';

        componentDidMount() {
            this.props.router.setRouteLeaveHook(this.props.route,this.routerWillLeave.bind(this));
        }

        routerWillLeave(nextLocation) {
            //nextLocation 接下来要跳转的路由
            //isChange 页面是否有更改
            return isChange ? false : true;
        }

        export default withRouter(Component);

 

二、h5和app的交互

1.其他第三方

因为我们项目不仅仅是内嵌在微信公众号、企业微信、钉钉里面的,还涉及到在原生app中app的功能调用h5页面,所以还涉及到和app的交互。

如果内嵌在比如微信公众号中,如果直接点左上角的X,就等于直接把这个页面关闭了,相当于浏览器的关闭页面,是无法监听到的,只有在点下面的<左箭头返回或者手势右滑,这样才被认为是页面的路由回退事件,这样才能监听到。

       

2.自己的app

但是我们的app中第一种情况是直接点击就进入到这个页面的,左上角的返回按钮是app中的,点返回就直接关闭页面了,监听不到路由回退,所以就不会生效。

还有一种情况是app进入到了h5页面,在h5页面点击又跳转了另一个h5页面。这时上方会有一个返回按钮和X按钮,点击X就是直接关闭页面了,点击返回就相当于h5页面直接的路由跳转,所以又能监听到路由回退事件,所以要考虑到这种。

如何解决这个问题呢,经过和app人员讨论之后,方案如下:

在app进入h5页面的时候,h5给app传递一个标识type,1表示需要在离开时进行二次确认,0表示取消标识。这样在h5的componentDidMount中传递给app一个标识,app接受到之后,就会控制app中的左上角的返回按钮,点击的话不会返回,而是调用h5的一个方法,传递参数,交给h5来处理,然后h5经过判断页面有没有更改之后,决定是否弹弹窗,在用户操作完之后,调用app提供的关闭页面的方法,关闭此页面,在componentWiilUnmount中再取消这个标识,防止出错。
这样以上的两种情况就都得到了解决,h5再跳转h5的情况,虽然点击的还是app的按钮,但由于我们再跳转h5的页面不传标识,所以点app的返回相当于路由回退,是没问题的。

1.向app传递标识的代码

export const appSendNeedConfirm = (type) => {
    const userAgentInfo = navigator.userAgent.match(/MyApp/i);
    const appVersion = getCurrVersion();

    if(userAgentInfo && compareVersion(appVersion,'2.2.3')){
        if(userAgentInfo.match(/Mac OS X/i)){
            try{
                window.webkit.messageHandlers.setNeedConfirm.postMessage(type);
            } catch (e) {
                window.setClosePageNeedConfirm(type);
            }
        }else {
            //无参数的话不用传null
            window.android.setNeedConfirm(type);
        }
    }
}

// 获取当前版本号
function getCurrVersion() {
    const userAgentInfo = navigator.userAgent;

    let singApp = userAgentInfo.indexOf('MyApp/');
    if(singApp !== -1) {
        let start = +singApp + 5;
        let end = userAgentInfo.indexOf(')', start);
        
        return userAgentInfo.substring(start, end);
    }
    return '';
}

2. 至于app如何调用h5的方法,我写在了componentDidMount中,在window上暴露这个方法,然后监听,如果app点击了返回就会调用此方法,并传一个参数type,来标识返回的类型,那么在回调中就能接收到,然后再进行相关判断逻辑的处理就可以了。

            //h5向app提供接口wannaClosePage参数 0/1,app调用之后,需要判断是否需要弹窗
            window.wannaClosePage = function(type){
               
                //这里的逻辑和routerWillLeave中判断是否更改的逻辑是一样的
            }

3.在保存接口执行完之后,h5调用app提供的方法,来关闭页面。

 

 

 

React Hooks 是 React 16.8 新增的特性,它使得函数组件可以拥有状态和生命周期等特性,这样就不再需要使用类组件。下面是一个使用 React Hooks 封装的弹窗组件的示例: ```jsx import React, { useState } from 'react'; function Modal(props) { const [isOpen, setIsOpen] = useState(false); const handleOpen = () => { setIsOpen(true); }; const handleClose = () => { setIsOpen(false); }; return ( <div> <button onClick={handleOpen}>Open Modal</button> {isOpen && ( <div> <div className="overlay" onClick={handleClose}></div> <div className="modal"> <h1>{props.title}</h1> <p>{props.content}</p> <button onClick={handleClose}>Close Modal</button> </div> </div> )} </div> ); } export default Modal; ``` 这个组件包含两个状态:`isOpen` 表示弹窗是否打开,`setIsOpen` 是更新状态的方法。当用户点击打开弹窗的按钮,调用 `handleOpen` 方法,将 `isOpen` 设置为 `true`,弹窗就会显示出来。当用户点击关闭弹窗的按钮或者点击弹窗外的区域,调用 `handleClose` 方法,将 `isOpen` 设置为 `false`,弹窗就会关闭。 使用这个组件,可以这样写: ```jsx import React from 'react'; import Modal from './Modal'; function App() { return ( <div> <Modal title="Modal Title" content="Modal Content" /> </div> ); } export default App; ``` 这个示例中,渲染了一个 Modal 组件,并传递了必要的属性,如标题和内容。用户点击打开弹窗的按钮,就会弹出一个 Modal 组件。 这个组件的优点在于它使用了 React Hooks,将状态和事件都封装在了组件内部,使得代码更加简洁和易于维护。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值