JS區(qū)分瀏覽器中頁面刷新與關(guān)閉標(biāo)簽頁

Web開發(fā)者在系統(tǒng)開發(fā)中經(jīng)常要面對產(chǎn)品經(jīng)理各式各樣的需求,當(dāng)然,大部分對產(chǎn)品體驗還是有幫助的,例如我們今天提到的刷新頁面,前進(jìn)后退,關(guān)閉瀏覽器標(biāo)簽時,為了避免用戶誤操作,需給出二次確認(rèn)提示框,這個相信大家都非常熟悉了,采用瀏覽器提供的BOM事件機制就可以解決,使用window對象的onbeforeunload事件即可,如果產(chǎn)品經(jīng)理只提出這樣的需求,那確實無可厚非,然而其需要的不僅僅是這些...

例如,我們一次項目開發(fā)中,產(chǎn)品經(jīng)理就針對我們的實現(xiàn)提出了“改進(jìn)方案”:

  1. 你們這彈出框太丑了,跟系統(tǒng)整體風(fēng)格不搭調(diào)啊,不能使用咱們自己組件庫中的Dialog嗎?很好的問題...我只想說,you can you up...
  2. 你們這刷新和關(guān)閉標(biāo)簽頁中展示的文案一樣啊,需要區(qū)分對待下,刷新提示XXX,關(guān)閉時提示SSS,這樣用戶才能更明確。恩,考慮到了用戶的體驗,很好,我還是想說,you can you up...其實,瀏覽器在關(guān)閉和刷新時,本身已經(jīng)區(qū)別對待了,提示是不同的,只不過我們自定義的部分并不能顯示不同的文案而已;當(dāng)然,也有一些hack的方法,但是很難適應(yīng)多個瀏覽器,各瀏覽器內(nèi)部對于關(guān)閉標(biāo)簽頁和刷新的實現(xiàn)機制會有所不同;
  3. 你們每次登錄進(jìn)來,為什么要延時10秒,才讓坐席簽入電話系統(tǒng)?。ㄎ覀冏龅氖强头到y(tǒng))?能不能把這個限制去掉啊,用戶體驗太不好了!我們也想去掉啊,但是電話系統(tǒng)頻繁簽入簽出會有問題,用戶刷新了瀏覽器,再次簽入,如果相隔時間很短的話,電話系統(tǒng)會出現(xiàn)故障,為了避免這個問題,我們才加上了這個限制,但是回過頭來思考,就可以進(jìn)入我們今天討論的主題了;

區(qū)分刷新與關(guān)閉標(biāo)簽頁

我們無法根據(jù)瀏覽器事件區(qū)分刷新還是關(guān)閉標(biāo)簽頁,進(jìn)而在相應(yīng)動作觸發(fā)前,執(zhí)行不同的動作,但是對于上文中產(chǎn)品提出的第三點意見,其實還是可以考慮優(yōu)化一下的,就是只有在刷新的時候延時10秒,新登錄或關(guān)閉標(biāo)簽頁一段時間之后再進(jìn)來時不延時;

要做到這點其實也很簡單,使用瀏覽器的本地存儲機制就可以實現(xiàn),例如cookie,LocalStorage等,這里就不能使用SessionStorage了,因為本次回話結(jié)束后,該緩存就失效了;由于在cookie中存儲會增加cookie的字節(jié)數(shù),每次請求中相應(yīng)的網(wǎng)絡(luò)傳輸量會增加,因此,我們采用了LocalStorage;其操作很簡單,我們使用的前端框架是AngularJS,具體如下:

const MAX_WAIT_TIME = 10;
const currentDate = new Date().getTime();
const lastestLeaveTime = parseInt(this.$window.localStorage.getItem('lastestLeaveTime'), 10) || currentDate;
this.secondCounter = Math.max(MAX_WAIT_TIME - Math.ceil((currentDate - lastestLeaveTime) / 1000), 0);
if (this.secondCounter > 0) {
  this.logoutTimeInterval = this.$interval(()=> {
    this.secondCounter--;
    this.$scope.$digest();
  }, 1000, this.secondCounter, false).then(() => {
    this.updateByStatus(this.AvayaService.status.OFFLINE);
  });
} else {
  this.updateByStatus(this.AvayaService.status.OFFLINE);
}

上面代碼主要作用是,進(jìn)入系統(tǒng)后,會先去LocalStorage中獲取上次退出時的時間,再獲取當(dāng)前時間,兩個時間進(jìn)行減法,如果值小于10秒,我們就認(rèn)為這是刷新,如果值大于10秒,我們認(rèn)為是關(guān)閉標(biāo)簽頁或新登錄,進(jìn)而可以執(zhí)行不同的方法,讓客服有更好的體驗,不用每次進(jìn)入系統(tǒng)都要等待10秒才能簽入電話系統(tǒng)了,產(chǎn)品經(jīng)理還是很重要的,吼吼,要不是他的疑問,可能我們也不會來優(yōu)化這個地方了...當(dāng)然,其實RD也要逐漸培養(yǎng)這種用戶體驗至上的思維,哪怕有一點可提升客服效率的地方,都值得我們花時間來優(yōu)化;

下面把相關(guān)退出的代碼也貼一下吧,前面忘說了,不管是刷新,還是關(guān)閉標(biāo)簽頁,只要是頁面銷毀,我們都會去執(zhí)行登出電話系統(tǒng)的操作,所以每次進(jìn)來后需要重新簽入;

//刷新頁面或者關(guān)閉頁面
$window.onbeforeunload = () => {
   return '操作將會導(dǎo)致頁面數(shù)據(jù)清空,請謹(jǐn)慎操作...';
};
//每次頁面unload時,設(shè)置LocalStorage時間;
$window.onunload = () => {
  $window.localStorage.setItem('lastestLeaveTime', new Date().getTime());
};

我們可能還注意到一些問題,那就是刷新,關(guān)閉頁面,前進(jìn)后退,你需要跳出瀏覽器默認(rèn)二次確認(rèn)框,但是用戶點擊退出系統(tǒng)按鈕,則必須彈出自己組件庫中的Dialog了,還必須不能兩個都彈出,具體代碼如下:

onStatusClick(index, name) {
  if (name === '退出') {
    this.mgDialog.openConfirm({
      showClose: false,
      template: 'app/header/logoutDialog.html',
      controller: 'HeaderDialogController as dialog',
      data: {
        'title': '您確定要退出系統(tǒng)嗎?'
      }
    }).then(() => {
      this.$window.location.href = '/logout';
      this.$window.onbeforeunload = null;
    });
  } else {
    // 內(nèi)部操作,大家不用管
    ...
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,765評論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,046評論 4 61
  • 這鬼天氣 這鬼天氣,真調(diào)皮,昨日在秋天,宛若夏季,薄裙短袖橫...
    拙蘭閱讀 910評論 10 19
  • 365天寫作訓(xùn)練計劃宛如白居易所寫的那個猶抱琵琶半遮面,千呼萬喚始出來的琵琶女。 心心念念的訓(xùn)練營終于拉開了帷幕,...
    四點半的洛杉磯閱讀 548評論 5 13

友情鏈接更多精彩內(nèi)容