vue记录路由历史+el-scrollbar,实现路由历史标签化
tag点击事件,调用方法计算scrollbr宽度,计算tag宽度,计算tag距离left(左边)多少px。tag宽度+距离右边再加20px左右,如果大于scrollbr宽度,证明tag所在位置已经到了最右边,实现点击tag之后scrollbr跟随滚动。4、把scrollbar和tag封装成组件,通过点击tag,获取tag位置,并计算scrollbar和tag宽度,实现根据tag位置,scrollb
·
概述:通过beforeEach拦截。vuex+sessionStorage实现持久化(路由历史应该随浏览器关闭而清空)。el-scrollbar elementUi 的隐藏组件实现滚动条。
tag点击事件,调用方法计算scrollbr宽度,计算tag宽度,计算tag距离left(左边)多少px。tag宽度+距离右边再加20px左右,如果大于scrollbr宽度,证明tag所在位置已经到了最右边,实现点击tag之后scrollbr跟随滚动。
初始化数据渲染完成之后,通过当前路由获取下标,实现初始化计算。
1、利用路由守位前卫beforeEach拦截,每次路由记录到缓存。
import Vue from 'vue'
import VueRouter from 'vue-router'
import store from '../store'
// 导航首位拦截,判断是否登录,及访问权限
router.beforeEach((to, from, next) => {
setRouterHistory(to)
})
// 记录路由历史
const setRouterHistory = (to) => {
let obj = {
title: to.meta.title,
path: to.path,
}
let routerHistory = store.state.app.routerHistory;
routerHistory.push(obj);
//map去重,避免重复记录重复路由
let mapArr = () => {
let map = new Map();
for (let item of routerHistory) {
if (!map.has(item.path)) {
map.set(item.path, item);
}
}
return [...map.values()];
}
let newArr = mapArr();
store.commit('setRouterHistory', newArr)
}
2、vuex+sessionStorage实现持久化 app.js
import storage from '../storage.js'
const session = "sessionStorage"
export default {
state: {
routerHistory: storage.getValue('routerHistory') || [],
nowRouter: storage.getValue('nowRouter'),
},
getters: {
routerHistory: state => state.app.routerHistory,
},
mutations: {
// 设置路由历史
setRouterHistory(state, routerHistory) {
state.routerHistory = routerHistory;
storage.setValue('routerHistory', routerHistory);
},
// 清除路由历史
cleanRouterHistory(state) {
state.routerHistory = [];
storage.cleanValue('routerHistory');
},
// 设置当前路由
setNowRouter(state, nowRouter) {
state.nowRouter = nowRouter;
storage.setValue('nowRouter', nowRouter);
},
// 清除当前路由
cleanNowRouter(state) {
state.nowRouter = undefined;
storage.cleanValue('nowRouter');
},
},
actions: {},
}
3、本地储存文件,路由历史应该关闭浏览器就清除,所以应该使用sessionStorage
export default {
setValue(key, value, type) {
if (typeof value == "object") {
// 如果是对象,就转字符串存储
value = JSON.stringify(value)
}
return window[type || 'localStorage'].setItem(key, value);
},
getValue(key, type) {
const data = window[type || 'localStorage'].getItem(key);
if (data) {
let value = data;
if ((data.indexOf('{') === 0 || data.indexOf('[') === 0) && data.indexOf(':') >= 0) {
// 如果是字符串对象,就转对象
value = JSON.parse(data)
}
return value
} else {
return false
}
},
cleanValue(key, type) {
window[type || 'localStorage'].removeItem(key);
}
}
4、把scrollbar和tag封装成组件,通过点击tag,获取tag位置,并计算scrollbar和tag宽度,实现根据tag位置,scrollbar跟随滚动
<template>
<div class="div_">
<el-scrollbar ref="scrollbar" :vertical="false" class="scrollbar_" @wheel.native.prevent="handleScroll">
<el-tag :ref="'tag'+index" v-for="(item, index) in routerHistory" :key="index" :closable="index!=0"
:type="nowRouter==item.path?'':'info'" @close="removeTag(item.path)" @click="tagClick(item.path,index)">
{{item.title}}
</el-tag>
</el-scrollbar>
</div>
</template>
<script>
import {
mapGetters
} from 'vuex'
export default {
data() {
return {
nowRouter: '',
}
},
computed: {
...mapGetters(["routerHistory"]),
},
watch: {
$route: {
handler: function(val, oldVal) {
this.nowRouter = val.path
this.$store.commit('setNowRouter', val.path)
},
// 深度观察监听
deep: true
}
},
created() {
this.nowRouter = this.$store.state.app.nowRouter;
// 通过当前路由获取路由下标
let nowRouterIndex = this.routerHistory.findIndex(item => item.path == this.nowRouter);
//在页面渲染完成后调用计算滚动条位置
this.$nextTick(() => {
this.countSroll(nowRouterIndex)
})
},
methods: {
removeTag(routerPath) {
// 删除tag返回新路由历史数组并存入vuex
let newArr = this.routerHistory.filter(item => item.path !== routerPath);
this.$store.commit('setRouterHistory', newArr)
// 如果删除的路由是当前路由,路由跳转至目前路由历史数组最后一个路由
if (this.$route.path == routerPath) {
this.$router.push({
path: newArr[newArr.length - 1].path
})
}
},
tagClick(path, index) {
this.countSroll(index);
this.$router.push(path);
},
countSroll(index) {
// 获取tag宽度
let tagWidth = this.$refs['tag' + index][0].$el.offsetWidth;
// 获取tag距离右边宽度
let tagMargin = this.$refs['tag' + index][0].$el.offsetLeft;
// 获取sroll宽度
let srollWidth = this.$refs.scrollbar.$el.offsetWidth;
// 如果tag距离右边+tag宽度+20左右已经大于sroll宽度,表示tag已经到了尽头了
if ((tagMargin + tagWidth + 20) > srollWidth) {
this.$refs.scrollbar.$refs.wrap.scrollLeft = tagMargin
} else {
this.$refs.scrollbar.$refs.wrap.scrollLeft = 0
}
},
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40
this.$refs.scrollbar.$refs.wrap.scrollLeft = this.$refs.scrollbar.$refs.wrap.scrollLeft + eventDelta / 4
},
},
}
</script>
<style lang="less" scoped>
.div_ {
height: 48px;
padding: 0 15px;
background-color: white;
box-sizing: border-box;
.scrollbar_ {
height: 100%;
width: 100%;
white-space: nowrap;
::v-deep .el-scrollbar__view {
height: 100%;
display: flex;
align-items: center;
}
}
}
.el-tag {
margin-left: 10px;
cursor: pointer
}
:first-child {
margin: 0;
}
</style>
5、home引用后,实现效果展示
更多推荐
已为社区贡献10条内容
所有评论(0)