Vue实现关联页⾯多级跳转(页⾯下钻)功能的完整实例
背景
在项⽬开发过程中,经常会遇到从上⼀个页⾯跳转到下⼀个页⾯的需求,俗称下钻。⽐如在概览页⾯的数据,需要查看详情,点击某个图表或按钮,即可跳转到详情页⾯查看详情数据。
⽬前为⽌,我们的项⽬中还没有⼀个统⼀的页⾯跳转⽅法,实现页⾯跳转的⽅式也因⼈⽽异,并且现有的很多项⽬只能在两个页⾯之间来回跳转,基本没有完整的实现多个页⾯互相跳转的功能。
关联页⾯跳转做为项⽬的常⽤功能,并且执⾏的都是重复性⾼的代码逻辑,⾮常有必要把相关的逻辑抽出来,封装成简单易⽤的公共⽅法和公共组件。
⽬的
统⼀各个项⽬的关联跳转⽅法逻辑,封装成简单易⽤的公共组件。
⽅案设计
⾸先,分析⼀下关联页⾯跳转⼤概的逻辑步骤:
1. 进⼊页⾯ A ;
2. 从页⾯A 跳转到页⾯ B ;
3. 进⼊页⾯ B ;
4. 返回页⾯ A ;
5. 进⼊页⾯ A ,即重新回到步骤 1 开始。
然后,对以上步骤进⾏细分:
1. 假设步骤 1 是正常进⼊页⾯,这时候没有逻辑需要处理;
2. 步骤 2 需要从页⾯ A 跳转到页⾯ B ,要实现这⼀步,就必需知道页⾯ B 的路由地址,通过 VueRouter 跳转到页⾯ B 的路由地址。
并且如果页⾯ B 需要的⼀些查询数据,就要把页⾯ B 的数据保存起来,等到步骤 3 使⽤;
3. 进⼊页⾯B 后,如果要获取页⾯ A 传过来的⼀些查询数据,就要先判断是不是从页⾯ A 跳转过来的,如果是,就从保存数据的地⽅
获取页⾯ A 传过来的数据;
4. 从页⾯ B 返回页⾯ A ,就必需知道页⾯ A 的路由地址,通过 VueRouter 跳转到页⾯ A 的路由地址。这⾥的路由地址,需要在步骤
2 跳转之前进⾏保存,这⾥才可以取到;
5. 可以发现,步骤1和步骤5都是进⼊页⾯ A ,但是执⾏的逻辑却不⼀样,所以,页⾯ A 如果要恢复跳转到页⾯ B 之前的⼀些数据,就
要先判断是不是从页⾯ B 跳转回来的,如果是,就从保存数据的地⽅获取跳转之前页⾯ A 的数据;这⾥的跳转之前的数据,需要在步骤 2 跳转之前进⾏保存,这⾥才可以取到。
接下来,为了实现上述的逻辑,我们先确定⽤来保存页⾯ A 和页⾯ B 的数据的⽅法,这⾥采⽤的是 VUEX 。再梳理⼀下以上逻辑步骤,画出流程图。
流程图
源页⾯
⽬标页⾯
具体实现
源页⾯跳转到⽬标页⾯
这⼀步的逻辑写在 VUEX 中,每次需要进⾏这⼀步操作,直接调 VUEX 中对应的⽅法即可。具体实现逻辑,就是先把源页⾯和⽬标页⾯的标识添加到路由参数上(⽬的是为了区分当前页⾯是进⾏的⽬标页⾯还是返回的源页⾯),再保存源页⾯和⽬标页⾯的数据,然后进⾏路由跳转。
在 store.js 中添加两个以下两个变量:
tgtPageParams: {}, // 关联跳转的⽬标页⾯数据(只保留⼀项数据)
srcPageParams: [], // 关联跳转的源页⾯数据(数组类型,保留多个页⾯的数据,可以多层返回,直到返回初始页⾯)
然后添加以下⽅法:
// 关联跳转,跳转到⽬标页⾯,并保存源页⾯和⽬标页⾯的数据到 Vuex
goTargetPage(state, options) {
/
/ 在源页⾯的 query 添加 tgtPageName 标识,记住⽬标页⾯
options.srcParams.query = Object.assign({}, options.srcParams.query, { tgtPageName: Params.name });
// 在⽬标页⾯的 query 添加 srcPageName 标识,记住源页⾯
state.srcPageParams.push(options.srcParams); // 保存源页⾯数据
router.push({ name: Params.name, query: Params.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 = PageParams;
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 || {}); // 将源页⾯传过来的数据更新到当前页⾯的 data(),以便页⾯进⾏查询
}
/
/ 如果当前页⾯是源页⾯
if (isSrcPage) {
Object.assign(vm.$data, srcParams.data || {}); // 跳转前保存的数据更新到当前页⾯的 data(),以便页⾯进⾏还原
storemit('popSourcePage'); // 将 srcPageParams 的最后⼀项数据删除
// 源页⾯关联跳转逻辑结束后,清除掉当前页路由上的⽬标页标识,防⽌刷新页⾯有问题
PageName;
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 && !PageName) {
this.$storemit('clearTargetPage');
this.$storemit('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
/*...省略的代码...*/vuejs流程图插件
mounted() {
vm = this;
vm.$changeVueData(vm); // 关联跳转相关页⾯,每次进⼊页⾯,必需执⾏ $changeVueData 函数,具体⽤法参考调⽤⽅法的注释
},
/*...省略的代码...*/
步骤 4,返回页⾯ A ,代码如下:
// 页⾯ B.vue
/*...省略的代码...*/
<template>
<div>
<backButton :backFn="$goSourcePage"></backButton>
/*...省略的代码...*/
</div>
</template>
/*...省略的代码...*/
总结
本⽂详细介绍了关联页⾯多级跳转(页⾯下钻)功能的实现,核⼼思想便是通过 VUEX 全局状态管理,保存关联跳转源页⾯和⽬标页⾯的数据,在跳转之前,把需要的数据保存起来,跳转到⽬标页⾯时,把⽬标页⾯需要的数据从 VUEX 中获取,跳转回源页⾯时,把源页⾯的数据从 VUEX 中恢复。
把这⼏个关键动作,封装成通⽤⽅法和组件,即统⼀了各个项⽬的关联页⾯跳转⽅式,也提⾼了代码的质量,更有利于后期维护。另外,⽂章中的容错部分,只写了⼀部分,如果后续需要继续完善该功能,可以把容错部分完善⼀下。
到此这篇关于Vue实现关联页⾯多级跳转(页⾯下钻)功能的⽂章就介绍到这了,更多相关Vue关联页⾯多级跳转内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论