如何让用户选择是否离开当前页面?

开发 前端
如果用户填写了很多数据此时,不小心点了其他a标签或者关闭了浏览器,不做判断,那么用户数据直接丢了。

为什么要让用户选择是否离开页面

  •  如果用户填写了很多数据此时
  •  不小心点了其他a标签或者关闭了浏览器,不做判断,那么用户数据直接丢了

梳理需求

  •  离开页面方式,被location.href,a标签,关闭浏览器或者当前tab页等...
  •  需要判断数据是否跟初始化时一致(用户有无填写表单...)
  •  用户选择离开就要继续逻辑,反之则不离开

正式开始

  •     首先要知道一个事件:onbeforeunload,MDN的说明是:当浏览器窗口关闭或者刷新时,会触发beforeunload事件。当前页面不会直接关闭,可以点击确定按钮关闭或刷新,也可以取消关闭或刷新。
  •    HTML规范指出在此事件中调用window.alert(),window.confirm()以及window.prompt()方法,可能会失效

实践一下

  •  在微信公众号编辑器界面,输入一部分内容后,点击关闭tab页,此时出现弹窗   

  • 删除所有内容后,回归初始进入的数据,点击关闭tab页,直接就关闭了,没有出现提示   

  • 看插件显示,这个编辑器界面没有使用react和vue,应该是jq吧,测试下控制台,对的,一猜就中(小编太🐂了,不点个关注?)

回到项目中,加入beforeunload事件

  •  HTML文件中加入script标签 
  1. <script type="text/javascript">  
  2.        window.onbeforeunload = function () {  
  3.            return "Leave this page?";  
  4.        }  
  5.    </script> 
  •     点击关闭,或者此时输入window.location.href= "xxx.ooo.com"会出现

  •  那么问题来了,如果我通过a标签跳转呢?

通过a标签跳转(+前端路由)

  •  我使用的是dva/router,引入相关组件 
  1. import { Prompt } from 'dva/router';  
  2. ....  
  3. render(){  
  4.   return <Prompt message={this.handlePrompt} />  
  •  引入Prompt组件,并且传入message是一个方法,看看这个方法   
  1. public handlePrompt = (location: Location) => {  
  2.        return false;  
  3.    }; 
  •  那么此时我们使用dva/router的history.push方法去跳转前端路由,就不能跳了,因为handlePrompt一直返回false,除非返回ture,否则这个页面通过a标签就无法跳转了...   

  • 此时无论怎么点击一键开启都不会有效果,那么改成return true试试 
  1. public handlePrompt = (location: Location) => {  
  2.       return true;  
  3.   }; 
  •  一跳就过去了

问题来了,怎么判断是否需要跳转呢?

  •  参考微信公众号编辑器,如果你编辑了内容后(跟初始进入的数据不一致),而且你是通过页面内a标签跳转的,那么就出现弹窗确认)

  •  那么很简单,我们使用antd的Modal组件,以及lodash的deepclone(深拷贝)、_.isEqual(value, other)执行深比较来确定两者的值是否相等。

    ❝    注意: isEqual这个方法支持比较 arrays, array buffers, booleans, date objects, error objects, maps, numbers, Object objects, regexes, sets, strings, symbols, 以及 typed arrays. Object 对象值比较自身的属性,不包括继承的和可枚举的属性。不支持函数和DOM节点比较。    ❞

实现思路讲解

  •  组件初始化时候,深拷贝一份表单数据存入组件中
  •  当用户通过a标签离开页面时,触发handlePrompt方法,存储离开的目的url,此时使用isEqual比较当前的数据和组件初始化的表单数据是否一致,如果不一致则出现弹窗,让用户选择是否离开
  •  代码实现: 
  1. // 处理自定义离开弹窗  
  2.   handlePrompt =(location )=> 
  3.     // 如果当前的保存为false,则弹窗提醒用户进行保存操作  
  4.     if (!this.isSave) {  
  5.       this.showModalSave(location);  
  6.       return false;  
  7.     }  
  8.     return true;  
  9.   }  
  10.   // 展示离开的提示的弹窗  
  11.   showModalSave = location => {  
  12.     this.setState({  
  13.       modalVisible: true,  
  14.       location,  
  15.     });  
  16.   } 
  17.    // 点击确认,进行页面保存操作,和保存成功后路由的跳转  
  18.   handleSaveAuto = () => {  
  19.     const { location } = this.state;  
  20.     const { history } = this.props;  
  21.     this.isSave = true 
  22.     this.setState({  
  23.       modalVisible: false,  
  24.     });  
  25.     //进行保存操作的处理,这里可以换成自己点击确认后需要做的操作  
  26.     this.handleSavePaper('save','exit',location.pathname)  
  27.   } 
  •  离开逻辑 
  1. // 取消是的路由跳转  
  2.   gotoNewUrl(url){  
  3.     const {dispatch,history } = this.props  
  4.     dispatch(routerRedux.push({  
  5.       pathname:url,  
  6.     }));  
  7.   }  
  8.   // 点击取消关闭弹窗  
  9.   closeModalSave=()=> 
  10.     const { location } = this.state;  
  11.     const {dispatch,history } = this.props  
  12.     this.isSave = true 
  13.     this.setState({  
  14.       modalVisible: false,  
  15.     },()=> 
  16.       this.gotoNewUrl(location.pathname)  
  17.     });  
  18.   } 
  •  html结构 
  1. <Prompt message={this.handlePrompt}/>  
  2. <Modal  
  3.     title="温馨提示"  
  4.     visible={this.state.modalVisible}  
  5.     closable={false}  
  6.     centered  
  7.     onCancel={this.closeModalSave}  
  8.     footer={null}  
  9. >  
  10.   <p>即将离开当前页面,是否保存当前修改?</p> 
  11.   <div style={{textAlign:'right'}}>  
  12.     <Button type='primary' onClick={this.handleSaveAuto}>保存</Button>  
  13.     <Button style={{marginLeft:'20px'}} onClick={this.closeModalSave}>取消</Button>  
  14.   </div>  
  15. </Modal> 

 

责任编辑:庞桂玉 来源: 前端大全
相关推荐

2009-12-04 13:14:19

PHP Global变

2022-07-03 17:55:53

HTTP页面浏览器

2013-04-17 10:54:18

Windows PhoWindows Pho

2023-04-26 08:18:48

FormPrompt表单更改

2021-04-06 11:07:02

字节跳动组织架构

2015-06-30 09:44:41

公有云游戏游戏云

2013-07-12 13:24:19

App诱惑

2020-04-20 14:50:02

前端技巧优化

2019-03-25 08:30:20

腾讯互联网

2023-03-08 12:44:00

谷歌AI区块链

2015-09-02 11:42:27

桌面云深信服

2013-07-05 13:48:47

App

2022-02-03 23:50:11

Windows 11Windows 10微软

2021-05-31 07:18:46

SpringSecurity信息

2016-03-21 13:24:22

apk安卓开发

2021-03-15 07:43:17

腾讯工作事业

2020-07-14 14:40:05

激光喷墨打印

2022-03-24 14:49:57

HTTP前端

2009-07-17 13:35:41

微软操作系统Windows 7升级方案

2009-07-25 12:09:29

Windows网络浏览器
点赞
收藏

51CTO技术栈公众号