如何讓用戶選擇是否離開當前頁面?
作者:佚名
如果用戶填寫了很多數據此時,不小心點了其他a標簽或者關閉了瀏覽器,不做判斷,那么用戶數據直接丟了。
為什么要讓用戶選擇是否離開頁面
- 如果用戶填寫了很多數據此時
- 不小心點了其他a標簽或者關閉了瀏覽器,不做判斷,那么用戶數據直接丟了
梳理需求
- 離開頁面方式,被location.href,a標簽,關閉瀏覽器或者當前tab頁等...
- 需要判斷數據是否跟初始化時一致(用戶有無填寫表單...)
- 用戶選擇離開就要繼續邏輯,反之則不離開
正式開始
- 首先要知道一個事件:onbeforeunload,MDN的說明是:當瀏覽器窗口關閉或者刷新時,會觸發beforeunload事件。當前頁面不會直接關閉,可以點擊確定按鈕關閉或刷新,也可以取消關閉或刷新。
- HTML規范指出在此事件中調用window.alert(),window.confirm()以及window.prompt()方法,可能會失效
實踐一下
- 在微信公眾號編輯器界面,輸入一部分內容后,點擊關閉tab頁,此時出現彈窗
- 刪除所有內容后,回歸初始進入的數據,點擊關閉tab頁,直接就關閉了,沒有出現提示
- 看插件顯示,這個編輯器界面沒有使用react和vue,應該是jq吧,測試下控制臺,對的,一猜就中(小編太🐂了,不點個關注?)
回到項目中,加入beforeunload事件
- HTML文件中加入script標簽
- <script type="text/javascript">
- window.onbeforeunload = function () {
- return "Leave this page?";
- }
- </script>
- 點擊關閉,或者此時輸入window.location.href= "xxx.ooo.com"會出現
- 那么問題來了,如果我通過a標簽跳轉呢?
通過a標簽跳轉(+前端路由)
- 我使用的是dva/router,引入相關組件
- import { Prompt } from 'dva/router';
- ....
- render(){
- return <Prompt message={this.handlePrompt} />
- }
- 引入Prompt組件,并且傳入message是一個方法,看看這個方法
- public handlePrompt = (location: Location) => {
- return false;
- };
- 那么此時我們使用dva/router的history.push方法去跳轉前端路由,就不能跳了,因為handlePrompt一直返回false,除非返回ture,否則這個頁面通過a標簽就無法跳轉了...
- 此時無論怎么點擊一鍵開啟都不會有效果,那么改成return true試試
- public handlePrompt = (location: Location) => {
- return true;
- };
- 一跳就過去了
問題來了,怎么判斷是否需要跳轉呢?
- 參考微信公眾號編輯器,如果你編輯了內容后(跟初始進入的數據不一致),而且你是通過頁面內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比較當前的數據和組件初始化的表單數據是否一致,如果不一致則出現彈窗,讓用戶選擇是否離開
- 代碼實現:
- // 處理自定義離開彈窗
- handlePrompt =(location )=>{
- // 如果當前的保存為false,則彈窗提醒用戶進行保存操作
- if (!this.isSave) {
- this.showModalSave(location);
- return false;
- }
- return true;
- }
- // 展示離開的提示的彈窗
- showModalSave = location => {
- this.setState({
- modalVisible: true,
- location,
- });
- }
- // 點擊確認,進行頁面保存操作,和保存成功后路由的跳轉
- handleSaveAuto = () => {
- const { location } = this.state;
- const { history } = this.props;
- this.isSave = true;
- this.setState({
- modalVisible: false,
- });
- //進行保存操作的處理,這里可以換成自己點擊確認后需要做的操作
- this.handleSavePaper('save','exit',location.pathname)
- }
- 離開邏輯
- // 取消是的路由跳轉
- gotoNewUrl(url){
- const {dispatch,history } = this.props
- dispatch(routerRedux.push({
- pathname:url,
- }));
- }
- // 點擊取消關閉彈窗
- closeModalSave=()=>{
- const { location } = this.state;
- const {dispatch,history } = this.props
- this.isSave = true;
- this.setState({
- modalVisible: false,
- },()=>{
- this.gotoNewUrl(location.pathname)
- });
- }
- html結構
- <Prompt message={this.handlePrompt}/>
- <Modal
- title="溫馨提示"
- visible={this.state.modalVisible}
- closable={false}
- centered
- onCancel={this.closeModalSave}
- footer={null}
- >
- <p>即將離開當前頁面,是否保存當前修改?</p>
- <div style={{textAlign:'right'}}>
- <Button type='primary' onClick={this.handleSaveAuto}>保存</Button>
- <Button style={{marginLeft:'20px'}} onClick={this.closeModalSave}>取消</Button>
- </div>
- </Modal>
責任編輯:龐桂玉
來源:
前端大全