vue用戶長時間不操作退出到登錄頁的兩種實(shí)現(xiàn)方式
問題描述
產(chǎn)品說,出于安全考慮,用戶長時間不操作,就回到登錄頁面,讓用戶重新登錄,就像銀行的app一樣。本文就記錄一下實(shí)現(xiàn)這種效果的兩種方式,分別是前端控制和后端控制,各有細(xì)節(jié)及適用使用場景
前端控制(方式一)
思路
首先,用戶長時間不操作具體表現(xiàn)形式是啥?其實(shí)就是事件是否長時間沒有被觸發(fā)執(zhí)行。
比如用戶長時間不操作,就沒有鼠標(biāo)點(diǎn)擊(click)事件、鼠標(biāo)滾輪(mousewheel)事件、鼠標(biāo)移動(mousemove)事件之類的,我們只需要監(jiān)聽這些事件,如果這些事件長時間沒有觸發(fā),就說明用戶長時間未操作,然后路由跳轉(zhuǎn)到登錄頁面即可。
這三個事件我選擇的是比較實(shí)用的鼠標(biāo)點(diǎn)擊事件,我們知道,一般來說項目的第一個頁面是登錄頁面,所以在登錄頁面用戶點(diǎn)擊登錄按鈕的時候,就記錄一下點(diǎn)擊登錄按鈕的時間,存儲到sessionstorage中去,當(dāng)跳轉(zhuǎn)到主頁面的時候,當(dāng)用戶每點(diǎn)擊一次頁面,就更新一下sessionstorage中的存儲的時間,同時也給頁面綁定一個循環(huán)定時器,間隔一段時間就把當(dāng)前時間和sessionstorage儲存的上一次點(diǎn)擊事件的時間做一個差值對比,當(dāng)差值超過一定時間,就強(qiáng)制用戶退出到登錄頁面即可。
代碼
login.vue頁面
// html
<el-button type="primary" @click="loginIn">點(diǎn)擊登錄</el-button>
// js
methods: {
loginIn() {
// 存第一份點(diǎn)擊的時間
sessionStorage.setItem("lastClickTime", new Date().getTime());
// 模擬后端返回存一個token
sessionStorage.setItem('token',"token")
this.$router.push({
path: "/",
});
},
}
Home.vue頁面
<template>
<div class="homeBox">
<!-- 左邊是菜單層級 -->
<div class="left">
<div class="leftNav">
<el-menu
:default-active="activeIndex"
class="elMenu"
background-color="#333"
text-color="#B0B0B2"
active-text-color="#fff"
:unique-opened="true"
router
ref="elMenu"
>
<el-menu-item index="/vue">
<i class="el-icon-location-outline"></i>
<span slot="title">vue頁面</span>
</el-menu-item>
<el-menu-item index="/react">
<i class="el-icon-star-off"></i>
<span slot="title">react頁面</span>
</el-menu-item>
<el-menu-item index="/angular">
<i class="el-icon-pear"></i>
<span slot="title">angular頁面</span>
</el-menu-item>
</el-menu>
</div>
</div>
<!-- 右邊是視圖層級 -->
<div class="right">
<div class="rightTop">
<el-button type="primary" plain @click="loginOut">登出</el-button>
</div>
<div class="rightBottom">
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
activeIndex: this.$route.path,
timer: null,
};
},
created() {
/*
第一步:
組件初始化加載就綁定監(jiān)聽點(diǎn)擊事件,注意:addEventListener的第三個參數(shù),這里要加上。
因為第三個參數(shù)決定了是冒泡還是捕獲(false冒泡默認(rèn),true捕獲),因為綁定監(jiān)聽點(diǎn)擊事件,我們是在最
頂層的DOM位置進(jìn)行捕獲點(diǎn)擊事件,所以第三個參數(shù)true,要加上的,這樣的話,內(nèi)層的任意地方的點(diǎn)擊事件
我們就都能監(jiān)聽到了,然后存儲一下點(diǎn)擊的時間
*/
window.addEventListener(
"click",
() => {
// 為了方便,我們把點(diǎn)擊事件的時間直接存到sessionStorage中去,這樣方便獲取比較
sessionStorage.setItem("lastClickTime", new Date().getTime());
},
true
);
},
mounted() {
/*
第二步:
組件初始化加載時也要綁定一個定時器,通過定時器定時輪詢,去對比當(dāng)前時間和上次點(diǎn)擊的時間的差值
*/
this.isTimeOut();
},
methods: {
isTimeOut() {
// 使用定時器之前,要清除一下定時器
clearInterval(this.timer);
this.timer = setInterval(() => {
let lastClickTime = sessionStorage.getItem("lastClickTime") * 1; // 把上次點(diǎn)擊時候的字符串時間轉(zhuǎn)換成數(shù)字時間
let nowTime = new Date().getTime(); // 獲取當(dāng)前時間
console.log("當(dāng)前時間和之前點(diǎn)擊時間", nowTime, lastClickTime);
// 假設(shè)我們需求是:5秒鐘不進(jìn)行點(diǎn)擊操作,就提示登錄退出
if (nowTime - lastClickTime > 1000 * 5) {
// 提示一下用戶
this.$message({ type: "warning", message: "超時了,已退出登錄" });
// 這里要清除定時器,結(jié)束任務(wù)
clearInterval(this.timer);
// 最后返回到登錄頁
this.$router.push({ path: "/login" });
}
}, 1000);
},
},
beforeDestroy() {
// 最后一步,離開頁面的時候,清除一下定時器,也解綁點(diǎn)擊事件
clearInterval(this.timer);
window.removeEventListener("click", () => {}, true);
},
};
</script>
這里注意一下,層級對應(yīng)關(guān)系,我項目搭建的層級關(guān)系是Home.vue頁面是App.vue頁面的里面一層,也有對應(yīng)的視圖,視圖對應(yīng)的也是整個頁面的關(guān)系。根據(jù)層級和路由表路由視圖router-view關(guān)系,選擇合適的層級去綁定對應(yīng)的點(diǎn)擊事件和定時器即可。
即層級關(guān)系是要選擇和login.vue層級平行的下一級才行,否則就會在login.vue頁面也會執(zhí)行定時器和點(diǎn)擊綁定事件了
效果圖

后端控制(方式二)
思路
這種后端控制方式限制性沒有前端控制強(qiáng),但是也是可以用的。
我們知道用戶長時間不操作就不會有發(fā)請求,這種方式我們和后端商定如下:
當(dāng)用戶這一次的請求和上一次請求的間隔時間超過一定時間,比如超過半小時。那么后端返回的狀態(tài)碼就不是200了,就是一個特殊的狀態(tài)碼,比如是4567這個狀態(tài)碼,那么我們在前端的響應(yīng)攔截器中就可以加一個判斷,如果狀態(tài)碼是4567就說明請求超時了,說明用戶長時間未操作,這個時候直接路由跳轉(zhuǎn)到登錄頁面即可
后端通過JWT機(jī)制去控制返回的狀態(tài)碼
代碼
這里main.js中的Vue的實(shí)例對象我們將其掛載到全局對象window上,方便我們在響應(yīng)攔截器中使用vm對象上的路由跳轉(zhuǎn)方法
main.js文件
// 掛載到window對象上
window.vm = new Vue({
store,
router,
render: h => h(App),
}).$mount('#app')
響應(yīng)攔截器文件
http.interceptors.response.use((res) => {
console.log('注冊到全局上',vm);
var code = res.data.code;
if(code == 4567){ // 4567是超時狀態(tài)碼,看到這個標(biāo)識我們就讓用戶退出登錄
// 注意,這個時候路由跳轉(zhuǎn)就不是this.$router.push()了
vm._router.push({ path: "/login" });
}
return res.data
}, (error) => {
// console.log(error)
return Promise.reject(error);
})
打印vm實(shí)例對象

所以在響應(yīng)攔截器中路由跳轉(zhuǎn)變成了vm._router.push({ path: "/login" })了
總結(jié)
上述兩種方式的思路都可以使用,具體使用哪種方式,視情況而定
到此這篇關(guān)于vue用戶長時間不操作退出到登錄頁的兩種實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)vue用戶長時間不操作退出內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決vant的Cascader級聯(lián)選擇組建css樣式錯亂問題
這篇文章主要介紹了解決vant的Cascader級聯(lián)選擇組建css樣式錯亂問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
element-UI el-table修改input值視圖不更新問題
這篇文章主要介紹了element-UI el-table修改input值視圖不更新問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02
webpack+vue.js實(shí)現(xiàn)組件化詳解
vue的開發(fā)體驗還是比較愉悅的。首先文檔非常友好,所以上手會比較快。其次,配合webpack和vue-loader,每個頁面都是一個.vue文件,寫起來很方便。所以很適合做組件化開發(fā),這篇文章我們就來一起看看webpack+vue.js如何實(shí)現(xiàn)組件化。2016-10-10
vue實(shí)現(xiàn)富文本編輯器詳細(xì)過程
Vue富文本的實(shí)現(xiàn)可以使用一些現(xiàn)成的第三方庫,如Quill、Vue-quill-editor、wangEditor等,這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)富文本編輯器的相關(guān)資料,需要的朋友可以參考下2024-01-01
使用vue-cli3 創(chuàng)建vue項目并配置VS Code 自動代碼格式化 vue語法高亮問題
這篇文章主要介紹了使用vue-cli3 創(chuàng)建vue項目,并配置VS Code 自動代碼格式化 vue語法高亮問題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05

