JS 頁面離開事件 頁面關閉事件,實現登錄成功返回上個頁面


壹 ❀ 引

登錄成功后跳轉到上一個頁面是很常見的需求,比如在天貓添加購物車時網站會效驗用戶登錄情況,若未登錄則跳轉登錄,登錄成功返回到先前的商品頁。

這個功能實現並不困難,但因為我的奇思妙想讓我先后了解了window.history對象以及窗口關閉/離開事件onbeforeunload,那么讓這個需求做個引子,讓我們開始一次有趣的探索之旅。

貳 ❀ 有趣的onbeforeunload

不管是從什么頁面進入的登錄頁,總是得先有個離開頁面的過程,那我在離開前一個頁面時先記住頁面,登錄成功調回來不就好了,所以我第一就想到了onbeforeunload事件。

關於onbeforeunload事件,MDN上說的很詳細,此事件在窗口即將被關閉(關閉瀏覽器 / 跳轉到其它頁面)時會觸發,看個例子:

window.onbeforeunload = function () {
    console.log('頁面要離開了。');
};

復制此代碼到瀏覽器控制台並回車執行,之后無論我們跳轉或關閉窗口,你會發現console都會執行。

onbeforeunload事件的使用場景其實很多,比如博客園博離開未保存的博客編輯窗口,再如信息較多的表單填寫等等,onbeforeunload主要起防止誤操作丟失頁面的作用,多一次挽回的機會。

值得一提的是onbeforeunload事件中無法使用window.open()以及window.alert()方法,若你使用,瀏覽器會拋出blocked xxxx during beforeunload類似的錯誤,意思就是在瀏覽器關閉前禁止使用彈窗或打開新窗口。

我們前面又說常用於離開頁面給出友好彈窗提示,不能用alert怎么實現呢,得換一種方式,這里貼出代碼:

window.onbeforeunload = function (e) {
    var e = e || window.event,
        dialogText = '頁面還未保存,確定要離開嗎?';
    // 兼容IE8和Firefox 4之前的版本
    if (e) {
        e.returnValue = dialogText;
    };
    // Chrome, Safari, Firefox 4+, Opera 12+ , IE 9+
    return dialogText;
};

當你運行這段代碼並嘗試關閉頁面時,你會看到頁面確實給出了如下提示:

但提示文字並沒有使用我們自己定義語句,這是因為瀏覽器在之后的版本中已統一提示語句,自定義語句只在低版本瀏覽器適用。

onbeforeunload這么好用,兼容性怎么樣呢,通過 can i use 一查,兼容性非常出色,完美兼容 IE6。

那么我有沒有使用onbeforeunload來處理登錄成功返回上個頁面呢?很遺憾並沒有,A頁面跳B頁面,B頁面跳C頁面,只要頁面跳轉此事件都會觸發,頁面跳轉本身就屬於高頻操作,性能代價太大。

叄 ❀ 歷史的掌控者history

我突然靈機一動!!!干嘛要自己去記錄頁面跳轉呢,window.history不是已經幫我們做了這件事嗎,想想還有點小激動。

打開瀏覽器控制台,輸入window.history並回車,可以看到如下屬性:

因為隱私問題,history對象早已不再展示用戶瀏覽記錄列表,只保留了go,back,forward以及HTML5新增的pushStatereplaceState方法用於操作頁面記錄。說通俗點,記錄我不給你看,但允許你操作。

新增的兩個方法我們先不說,這里主要說說前三個。我們來做個小實驗,先打開百度,跳轉到嗶哩嗶哩,再跳轉到騰訊視頻。現在打開控制台,輸入window.history.back()並回車,你會發現頁面從騰訊視頻跳到了嗶哩嗶哩。按下方向鍵 ↑ 再回車,頁面又回到了最初的百度。

現在輸入window.history.forward()並回車,頁面又會跳到B站,重復此操作,B站又跳到騰訊視頻。

其實不難理解,假設已經建立了A-B-C三個節點,使用back就是從此節點往回退,相反的,forward就是從此節點往前進。

我們在騰訊視頻頁面輸入window.history.go(-2),你會發現一下回到了百度,因為它等同於執行了2次back方法。對應的,輸入window.history.go(2)回車,頁面又能從百度回到騰訊,它等同於執行了2次forward方法,是不是很簡單。

於是我就想到了這樣的邏輯:

function login() {
    //do something...
    //返回上個頁面
    window.history.back();
};

於是某位用戶將網站的登錄頁添加到了收藏夾,打開瀏覽器顯示百度首頁,點擊收藏夾跳轉登錄頁,登錄成功后於是網站跳轉百度,用戶一臉懵逼....

很遺憾,history pass,不符合要求。

肆 ❀ 我的實現

使用onbeforeunload每個頁面都會觸發,性能不好,使用history我們是不用記錄了,結果記錄不受網站控制,網站外部也會記。那么我們就綜合一下,需要記錄的時候我們自己記。

一共也就兩個地方需要記憶,我們知道登錄一般都在頁頭,你想進入登錄頁必須點擊登錄按鈕,那么這個時候記錄就好了。

第二種情況就是程序跳轉登錄頁,比如token過期自動跳轉提示登錄,那么在程序中需要跳轉的地方也去記錄。

因為登錄屬於全站性的操作,你也不知道用戶在哪個頁面進入的登錄,所以像我這邊使用angularjs開發的項目,就在總module上注冊一個登錄相關的service,這里只說具體方法實現:

//  在跳轉登錄前調用,用於記錄當前頁面
function localStorgeUrl() {
    //取當前頁面地址,這里模擬是百度
    // let pathArr = window.location.pathname.split('/');
    // let url = pathArr[pathArr.length - 1];
    let url = 'http://www.baidu.com';
    //本地存儲該頁面
    window.localStorage.setItem('url', url);
};

function redirectUrl() {
    //獲取緩存路徑
    let url = window.localStorage.getItem('url');
    //假設用戶從外網進入登錄頁,取不到的情況跳轉首頁
    url ? location.href = url : location.href = 'index.html';
};

//登錄
function login() {
    // 登錄相關操作,假設登錄成功
    redirectUrl();
};

//跳轉登錄頁前調用
localStorgeUrl();
//開始登錄
login();

這里只是貼一個思路,如果有緣人看到有更好的做法,也歡迎討論。本文從實現功能登錄成功返回上個頁面為引子,介紹了頁面關閉事件onbeforeunload與history,也算一次不錯的學習,那么就寫到這里。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM