Vue實現關聯頁面多級跳轉(頁面下鑽)功能的完整例項
背景
在專案開發過程中,經常會遇到從上一個頁面跳轉到下一個頁面的需求,俗稱 下鑽 。比如在概覽頁面的資料,需要檢視詳情,點選某個圖表或按鈕,即可跳轉到詳情頁面檢視詳情資料。
目前為止,我們的專案中還沒有一個統一的頁面跳轉方法,實現頁面跳轉的方式也因人而異,並且現有的很多專案只能在兩個頁面之間來回跳轉,基本沒有完整的實現多個頁面互相跳轉的功能。
關聯頁面跳轉做為專案的常用功能,並且執行的都是重複性高的程式碼邏輯,非常有必要把相關的邏輯抽出來,封裝成簡單易用的公共方法和公共元件。
目的
統一各個專案的關聯跳轉方法邏輯,封裝成簡單易用的公共元件。
方案設計
首先,分析一下關聯頁面跳轉大概的邏輯步驟:
- 進入 頁面 A ;
- 從 頁面A 跳轉到 頁面 B ;
- 進入 頁面 B ;
- 返回 頁面 A ;
- 進入 頁面 A ,即重新回到步驟 1 開始。
然後,對以上步驟進行細分:
- 假設步驟 1 是正常進入頁面,這時候沒有邏輯需要處理;
- 步驟 2 需要從 頁面 A 跳轉到 頁面 B ,要實現這一步,就必需知道 頁面 B 的路由地址,通過 vueRouter 跳轉到 頁面 B 的路由地址。並且如果 頁面 B 需要的一些查詢資料,就要把 頁面 B 的資料儲存起來,等到步驟 3 使用;
- 進入 頁面B 後,如果要獲取 頁面 A 傳過來的一些查詢資料,就要先判斷是不是從 頁面 A 跳轉過來的,如果是,就從儲存資料的地方獲取 頁面 A 傳過來的資料;
- 從 頁面 B 返回 頁面 A ,就必需知道 頁面 A 的路由地址,通過 VueRouter 跳轉到 頁面 A 的路由地址。這裡的路由地址,需要在步驟 2 跳轉之前進行儲存,這裡才可以取到;
- 可以發現程式設計客棧,步驟1和步驟5都是進入 頁面 A ,但是執行的邏輯卻不一樣,所以, 頁面 A 如果要恢復跳轉到 頁面 B 之前的一些資料,就要先判斷是不是從 頁面 B 跳轉回來的,如果是,就從儲存資料的地方獲取跳轉之前 頁面 A 的資料;這裡的跳轉之前的資料,需要在步驟 2 跳轉之前進行儲存,這zdtWTvei裡才可以取到。
接下來,為了實現上述的邏輯,我們先確定用來儲存 頁面 A 和 頁面 B 的資料的方法,這裡採用的是 VUEX 。再梳理一下以上邏輯步驟,畫出流程圖。
流程圖
源頁面
目標頁面
具體實現
源頁面跳轉到目標頁面
這一步的邏輯寫在 VUEX 中,每次需要進行這一步操作,直接調 VUEX 中對應的方法即可。具體實現邏輯,就是先把源頁面和目標頁面的標識新增到路由引數上(目的是為了區分當前頁面是進行的目標頁面還是返回的源頁面),再儲存源頁面和目標頁面的資料,然後進行路由跳轉。
在 store.js 中新增兩個以下兩個變數:
tgtPageParams: {},// 關聯跳轉的目標頁面資料(只保留一項資料) srcPageParams: [],// 關聯跳轉的源頁面資料(陣列型別,保留多個頁面的資料,可以多層返回,直到返回初始頁面)
然後新增以下方法:
// 關聯跳轉,跳轉到目標頁面,並儲存源頁面和目標頁面的資料到 Vuex goTargetPage(state,options) { // 在源頁面的 query 新增 tgtPageName 標識,記住目標頁面 options.srcParams.query = Object.assign({},options.srcParams.query,{ tgtPageName: options.tgtParams.name }); // 在目標頁面的 query 新增 srcPageName 標識,記住源頁面 options.tgtParams.query = Object.assign({},options.tgtParams.query,{ srcPageName: options.srcParams.name }); state.srcPageParams.push(options.srcParams); // 儲存源頁面資料 state.tgtPageParams = options.tgtParams; // 儲存目標頁面資料 router.push({ name: options.tgtParams.name,query: options.tgtParams.query }); // 跳轉到目標頁面 },
目標頁面返回源頁面
這一步的邏輯寫在 VUEX 中,每次需要進行這一步操作,直接調 VUEX 中對應的方法即可。具體實現邏輯,就是從 state.srcPageParams 中取到源頁面的資料(包括路由地址和引數),然後進行路由跳轉。
在 VUEX 中新增以下方法:
// 關聯跳轉,跳轉回源頁面 goSourcePage(state,vm) { let obj = state.srcPageParams.slice(-1)[0]; // 取陣列的最後一項 // 如果 Vuex 有上一頁的資料,則根據 Vuex 的資料返回上一面 if (obj && Object.keys(obj).length > 0) { router.push({ name: obj.name,query: obj.query }); // 進行跳轉 } // 如果 Vuex 中沒有上一頁的資料,但是路由上有上一頁的標誌,則根據路由標誌返回上一頁(這是為了防止在詳情頁中重新整理時,Vuex 資料丟失,無法返回上一頁的問題) else if (vm && vm.$route.query.srcPageName) { router.push({ name: vm.$route.query.srcPageName }); } },
進入目標頁面使用VUEX資料/返回源頁面恢復VUEX資料
這一步的邏輯是把上面方案設計中的 步驟 3 和 步驟 5 合併起來了,寫在公共函式檔案中,每次需要進行這一步操作,直接調 Vue.prototype 中對應的方法即可。具體實現邏輯是:判斷當前頁面是源頁面還是目標頁面,如果是目標頁面,那就使用源頁面傳過來的資料,如果是源頁面,就恢復跳轉之前的資料。
在公共函式檔案 utils.js 中新增以下方法,並掛載到 Vue.prototype 上:
/**
* 關聯跳轉相關的頁面可以使用此方法
* 1、源頁面:可以把儲存到 Vuex 中的資料恢復到 data 中使用
* 2、目標頁面:可以把源頁面傳遞到 Vuex 中的資料放到 data 中使用
* 3、源頁面資料恢復後,刪除 Vuex 中對應的備份資料,刪除路由上儲存的目標頁標識
* @param vm {object} 必填 當前 Vue 元件例項
*/
$changeVueData: (vm) => {
let tgtParams = store.state.tgtPageParams;
let srcParams = vm.$store.state.srcPageParams.slice(-1)[0] || {}; // 取最後一個元素值
let name = vm.$route.name;
let query = vm.$deepCopyJSON(vm.$route.query); // 這裡深拷貝是因為 $route.query 需要更新
// 判斷當前頁是 目標頁面 還是 源頁面
// 判斷條件是 先判斷路由名是否一致,再判斷指定的 query 的屬性值是否也一致
let isTgtPage = tgtParams.name === name &&
(tgtParams.checkKeys ? tgtParams.checkKeys.every(key => tgtParams.query[key] === query[key]) : true);
let isSrcPage = srcParams.name === name &&
(srcParams.checkKeys ? srcParams.checkKeys.every(key => srcParams.query[key] === query[key]) : true);
// 如果當前頁面是目標頁面
if (isTgtPage) {
Object.assign(vm.$data,tgtParams.data || {}); // 將 源頁zdtWTvei面傳過來的資料 更新到當前頁面的 data(),以便頁面進行查詢
}
// 如果當前頁面是源頁面
if (isSrcPage) {
Object.assign(vm.$data,srcParams.data || {}); // 跳轉前儲存的資料 更新到當前頁面的 data(),以便頁面進行還原
store.commit('popSourcePage'); // 將 srcPageParams 的最後一項資料刪除
// 源頁面關聯跳轉邏輯結束後,清除掉當前頁路由上的目標頁標識,防止重新整理頁面有問題
delete query.tgtPageName;
vm.$router.push({ name,query });
}
},
返回上一頁按鈕
為了更方便的使用關聯跳轉功能,把返回上一頁按鈕封裝成了一個元件,具體實現程式碼如下:
// back-button.vue <template> <button class="primary-btn return-程式設計客棧btn" v-if="showBackBtn" @click="backFn"> <i class="return-icon"></i>{{ backText }} </button> </template> <script> export default { name: 'back-button',props: { // 返回上一頁的文字 backText: { type: String,default: () => '上一步' },// 返回上一頁的函式 backFn: { type: Function,default: () => {} } },data() { return { showBackBtn: false,}; },mounted() { this.setBackBtnShow(); },activated() { this.setBackBtnShow(); },methods: { // 更新返回上一頁按鈕的狀態 setBackBtnShow() { this.$nextTick(() => { let srcPage = this.$store.state.srcPageParams.slice(-1)[0]; this.showBackBtn = Boolean(srcPage && Object.keys(srcPage).length > 0); }); },},}; </script> <style scoped lang="scss"> </style>
容錯部分
考慮到關聯跳轉的過程中,有可能使用者會突然中斷,或者重新整理頁面等異常操作,設計了部分容錯機制:
// 根元件 App.vue /*...省略的程式碼...*/ watch: { // 監聽,當路由發生變化的時候執行 $route(to,from) { // 如果即不是源頁面,也不是目標頁面,則清空 Vuex 中儲存的資料 // 防止在關聯跳轉的過程中切換選單或者進行其他操作,導致 Vuex 中有上一次關聯跳轉殘留的資料 if (!to.query.srcPageName && !to.query.tgtPageName) { this.$store.commit('clearTargetPage'); this.$store.commit('clearSourcePage'); } 程式設計客棧 },/*...省略的程式碼...*/
使用示例
根據上述方案設計部分的步驟:
步驟 1 和步驟 5 ,進入 頁面 A ,邏輯在同個頁面,程式碼如下:
// 頁面 A.vue /*...省略的程式碼...*/ mounted() { vm = this; vm.$changeVueData(vm); // 關聯跳轉相關頁面,每次進入頁面,必需執行 $changeVueData 函式,具體用法參考呼叫方法的註釋 vm.ready(); },/*...省略的程式碼...*/ 步驟 2,從 頁面A 跳轉到 頁面 B ,程式碼如下: // 頁面 A.vue /*...省略的程式碼...*/ methods: { // 跳轉到 B 頁面 goUserSituation: function (name) { let srcParams = { name: vm.$route.name,query: vm.$route.query }; let tgtParams = { name: 'user-situation',data: { checkedSystem: name } }; vm.$goTargetPage(srcParams,tgtParams); },/*...省略的程式碼...*/
步驟 3,進入 頁面 B ,程式碼如下:
// 頁面 B.vue /*...省略的程式碼...*/ mounted() { vm = this; vm.$changeVueData(vm); // 關聯跳轉相關頁面,每次進入頁面,必需執行 $changeVueData 函式,具體用法參考呼叫方法的註釋 vm.ready(); },/*...省略的程式碼...*/ 步驟 4,返回 頁面 A ,程式碼如下: // 頁面 B.vue /*...省略的程式碼...*/ <template> <div> <backButton :backFn="$goSourcePage"></backButton> /*...省略的程式碼...*/ </div> </template> /*...省略的程式碼...*/
總結
本文詳細介紹了關聯頁面多級跳轉(頁面下鑽)功能的實現,核心思想便是通過 VUEX 全域性狀態管理,儲存關聯跳轉源頁面和目標頁面的資料,在跳轉之前,把需要的資料儲存起來,跳轉到目標頁面時,把目標頁面需要的資料從 VUEX 中獲取,跳轉回源頁面時,把源頁面的資料從 VUEX 中恢復。
把這幾個關鍵動作,封裝成通用方法和元件,即統一了各個專案的關聯頁面跳轉方式,也提高了程式碼的質量,更有利於後期維護。另外,文章中的容錯部分,只寫了一部分,如果後續需要繼續完善該功能,可以把容錯部分完善一下。
到此這篇關於Vue實現關聯頁面多級跳轉(頁面下鑽)功能的文章就介紹到這了,更多相關Vue關聯頁面多級跳轉內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!