• react实现浏览器的返回、前进、刷新,关闭拦截


    刷新和关闭拦截

    beforeunload 事件

    触发机制: 浏览器的刷新和关闭按钮被点击,点击跳转路由的按钮 (全局生效)
    侦听机制: 页面初始化和卸载时侦听事件
    缺点:

    • 默认样式,无法改变
    • 全局生效
    useEffect(()=>{
            window.addEventListener('beforeunload', beforeunload);
        },[])
    
        useEffect(()=>{
            window.addEventListener('beforeunload', beforeunload);
        },[])
    
        const beforeunload=(ev)=>{
            if (ev) {  
                   ev.returnValue = '';
                }
        }
    

    返回、前进的弹框拦截

    1.react-router-dom中的Prompt组件

    触发机制:浏览器的返回和前进按钮被点击(路由发生变化)
    缺点: 不能自定义样式

    import React from 'react'
    import {Prompt } from "react-router-dom"   
    
    export default function StopRoute(){
      const [isOpen,setIsOpen]=useState(false)
    
      const lanjieReturn=()=>{
      
      (location)=>{
         if(!isOpen) {
           let leave = window.confirm("您确定要离开该页面吗?")         
           if(!leave) {
             return false
           }          
         }else {
          setIsOpen(false)
        /* 返回false是拦截的关键 */
         return false
         }
       }
    
      }
    
      return (
        <>
            /* message是用来显示内容的   when是用来控制拦截的时机的(也就是弹框出现的时机) */
            <Prompt message="您确定要离开该页面吗?" when={isOpen} />       //第一种用法   message直接写字符串
            
             <Prompt                                                               //第二种用法     message是函数,但是函数内部只能是三木运算,且不用return   (其实质也就是用法一的直接写字符串)
               message = {() => {
               this.state.isOpen? false: "您确定要离开该页面吗?"
             }}
    
            <Prompt    message = {lanjieReture}/>  //第三种用法   mesage是函数,并且不是三目运算,则函数必须返回false,并且不能自定义弹框,因为react的显示必须写在render里面,这里的函数rentuen的是false,不是DOM,所以只能只用js的原生弹框来拦截
    
        </>
      )
    }
    

    2.useHistory().block

    触发机制: 浏览器的返回和前进按钮被点击
    缺点:

    • 用到的页面,其组件在路由或者在任何地方不能使用高阶组件(也就是不能再被别的组件包裹),否则失效
    • 如果用到的页面不是首页,那么进来的页面最好使用push,不能使用replace,否则不好使
    import React, {useEffect, useState} from 'react';
    import {useHistory} from 'react-router';
    import Dialog from '@/components/Dialog'
    
    export default function UserConfirmationTwo(props) {
        const {when = false} = props;
        const [isShowModal, setIsShowModal] = useState(false);
        const history = useHistory();
        const [nextLocation, setNextLocation] = useState(null);
        const [action, setAction] = useState();
        const [unblock, setUnblock] = useState(null);
    
        useEffect(() => {
            if (!when || unblock) {
                return;
            }
            const cancel = history.block((nextLocation, action) => {
                if (when) {
                    setIsShowModal(true);
                }
                setNextLocation(nextLocation);
                setAction(action);
                return false;
            });
            setUnblock(() => {
                return cancel;
            });
        }, [when, unblock]);
    
        useEffect(() => {
            return () => {
                unblock && unblock();
            };
        }, []);
    
        function onConfirm() {
            unblock && unblock();
            if (action === 'PUSH') {
                history.push(nextLocation);
            } else if (action === 'POP') {
                history.goBack();
            } else if (action === 'REPLACE') {
                history.replace(nextLocation);
            }
            props.closeStopRouteDialog(1);
            setIsShowModal(false);
     
        }
    
        function onCancel() {
            props.closeStopRouteDialog(0);    //点击取消和确定的事件
            setIsShowModal(false);
        }
    
        return (
            <>
                {isShowModal && <Modal
                    title="是否返回?"
                    width='450'
                    visible={isShowModal}
                    confirm={()=>onConfirm()}
                    close={onCancel}
                >
                </Modal>}
            </>
        );
    }
    
    

    3.pushState popState

    触发机制:浏览器的返回和前进按钮被点击
    缺点: 没缺点了,js原生的

    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            *{
                margin:0;
                padding:0;
            }
            .menu{
                 100px;
                height: 40px;
                font-size: 30px;
                line-height: 40px;
                text-align: center;
                border:1px solid #000000;
                float: left;
                margin-left: 50px;
                user-select: none;
            }
            p{
                clear: both;
                display: none;
            }
            .dialog{
                 100%;
                height: 100%;
                background: black;
                opacity: 0.5;
                position: absolute;
                top: 0;
                left: 0;
                display: none;
            }
            .container{
                 500px;
                height: 200px;
                position: absolute;
                z-index: 100;
                left:calc(50% - 250px);
                top:calc(50% - 100px);
                background: #FFFFFF;
                padding:24px;
                display: flex;
                flex-direction: column;
                align-items: start;
                justify-content: space-between;
            }
            .title{
                color:#000000;
                font-size: 30px;
                line-height: 30px;
                font-weight: 600;;
            }
            .btn{
                
            }
            .btnLeft{
                 50px;
                height: 30px;
                background-color:red;
                margin-right:395px;;
            }
            .btnRight{
                 50px;
                height: 30px;
                background-color:chartreuse
            }
           
        </style>
    </head>
    <body>
        <div class='menu'>水果</div>
        <div class='menu'>蔬菜</div>
        <div class='menu'>零食</div>
        <div class='menu'>饮料</div>
        <br>
        <br>
        <p>猕猴桃
            苹果
            梨</p>
        <p>白菜
            土豆
            地瓜</p>
        <p>辣条
            牛肉干
            薯片</p>
        <p>可乐
            雪碧
            果汁</p>
    
    
        <div class='dialog'>
            <div class='container'>
                <div class='title'>确定要返回吗</div>
                <div class="btn">
                    <button class='btnLeft'>取消</button>
                    <button class='btnRight'>确定</button>
                </div>
            </div>
        </div>
    
    
        <script>
            var arr,divs;
            let dialog=document.querySelector('.dialog')
            init()
            function init(){
                // 当历史前进或者后退时就会收到这个事件
                window.onpopstate=popStateHandler;
                arr=Array.from(document.getElementsByTagName("p"));
                divs=Array.from(document.querySelectorAll(".menu"));
                cancel=document.querySelector('.btnLeft')
                ensure=document.querySelector('.btnRight')
                arr[0].style.display="block";
                for(var i=0;i<divs.length;i++){
                    divs[i].onclick=clickHandler;
                }
                cancel.addEventListener('click',handleClick)
                ensure.addEventListener('click',handleClick)
                
            }
    
    
            function clickHandler(){
               var index=divs.indexOf(this);
            //    history.pushState({state:1},"","#"+this.innerHTML);
                // 在历史记录列表中增加数据,后面的#内容标示当前跳转部分
                 history.pushState({index:index}, "", document.URL);
                 changeMenu(index);
            }
    
            function popStateHandler(){
                console.log(history.state);
                // changeMenu(history.state.index)
                dialog.style.display='block'
            }
    
           function changeMenu(index){
            for(var i=0;i<arr.length;i++){
                    if(i===index){
                        arr[i].style.display="block";
                    }else{
                        arr[i].style.display="none";
                    }
                }
           }
    
           function handleClick(e){
            if(e.target.innerHTML==='确定'){
                dialog.style.display='none'
                console.log('点击了确定')
                location.href='http://www.baidu.com'
                return ;
            }
            dialog.style.display='none'
            console.log('点击了取消')
            // window.location.href='http://www.baidu.com'
           }
        </script>
    </body>
    </html>
    
  • 相关阅读:
    六、Linux计划任务及压缩归档
    四、用户管理
    三、vim编辑器详解
    八、RAID磁盘阵列及CentOS7系统启动流程
    五、权限管理
    二、Linux常用命令
    七、Linux磁盘管理及LVM讲解
    一、Linux常用命令
    JS继承的实现方式 原型 原型链 prototype和_proto_的区别
    js引用类型(Object、Array)
  • 原文地址:https://www.cnblogs.com/94-Lucky/p/14828661.html
Copyright © 2020-2023  润新知