参考TagsView原链接https://blog.csdn.net/Dream_xun/article/details/83146106
开发项目时,使用基础tagsView遇到的问题,代码基本上与原链接一致,仅有一些基础功能。
本人开发项目为Nuxt项目。
下面说一下遇到的问题,记录一下,算是避坑吧:
首先, <nuxt />改写
<transition name="fade-transform" mode="out-in">
<nuxt keep-alive :keep-alive-props="{ include: $store.state.tagsView.cachedViews }"
class="app-page" />
</transition>
1. TagsView.vue 的修改
1)更改了TagsView.vue的插槽slot内容 ,原代码ref="tag"中未加class="tags-view-item",需注意一下,另外样式不起作用,可先将下方style里的scope去掉,但要留意样式可能冲突。
<scroll-pane class="tags-view-wrapper" ref="scrollPane">
<span
v-for="tag in Array.from(visitedViews)"
ref="tag"
:key="tag.path"
:data-name="tag.name"
:data-path="tag.path"
:data-full-path="tag.fullPath"
:class="isActive(tag) ? 'active' : ''"
class="tags-view-item"
@click="() => goToPage(tag)"
@click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
@contextmenu.prevent="openMenu(tag, $event)"
>
{{ $t(`leftSideBar.pageList.${tag.title}`) }}
<span
v-if="!isAffix(tag)"
class="el-icon-close"
@click.prevent.stop="closeSelectedTag(tag)"
/>
</span>
</scroll-pane>
2) 自定义首页的标签配置,可参考。pageKey根据项目需要,可能是其他字段。
import ScrollPane from '@/components/tagViews/ScrollPane';
// 自定义首页的标签配置,下面的route2View方法中使用
const indexViewInfo = {
path: '/',
fullPath: '/',
name: 'lang',
title: 'home',
meta: {
pageKey: 'home',
noCache: false,
affix: true,
icon: undefined
}
};
export default {
3)methods方法的更改,仅做了修改了方法的记录
// 例如首页一般不需要关闭页签
isAffix(tag) {
return tag.meta && tag.meta.affix;
},
// 可以对跳转的页签做些操作,如我这个对国际化跳转时页签做了调整
goToPage(tag) {
const locale = `/${this.$store.app.i18n.locale}/`;
const oriLocale = tag.path.substring(0, 4);
const pathLocale = tag.path.replace(oriLocale, locale);
this.$router.push({
path: pathLocale,
query: tag.query
});
},
// 原代码addViewTags方法在添加tab页签数组时,会造成泄露
// 报错:Error in render: "RangeError: Maximum call stack size exceeded
addViewTags() {
if (this.$route.path.startsWith('/redirect')) {
return;
}
this.route2View();
if (this.routeView) {
this.$store.dispatch('tagsView/addVisitedViews', this.routeView);
}
},
// indexViewInfo定义在import下面,export default上面
route2View() {
if (this.$route.path === '/') {
this.routeView = indexViewInfo;
} else {
const cachedViewName = this.$route.name;
this.routeView = {
meta: this.$route.meta,
path: this.$route.path,
query: this.$route.query,
fullPath: this.$route.fullPath,
name: cachedViewName
};
}
},
moveToCurrentTag() {
const tags = this.$refs.tag;
this.$nextTick(() => {
for (const tag of tags) {
// 以组件name为标准匹配
if (tag.getAttribute('data-name') === this.$route.name) {
this.$refs.scrollPane.moveToTarget(tag.$el);
break;
}
}
});
}
2. ScrollPAne.vue,位置定位方法修改
moveToTarget(currentTag) {
const $container = this.$refs.scrollContainer;
const $containerWidth = $container.offsetWidth;
const $scrollWrapper = this.scrollWrapper;
const tagList = this.$parent.$refs.tag;
let firstTag = null;
let lastTag = null;
// find first tag and last tag
if (tagList.length > 0) {
firstTag = tagList[0];
lastTag = tagList[tagList.length - 1];
}
if (firstTag === currentTag) {
$scrollWrapper.scrollLeft = 0;
} else if (lastTag === currentTag) {
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth;
} else {
// find preTag and nextTag
const currentIndex = tagList.findIndex(item => item === currentTag);
const prevTag = tagList[currentIndex >= 1 ? currentIndex - 1 : 0];
const nextTag = tagList[currentIndex + 1];
// the tag's offsetLeft after of nextTag
const afterNextTagOffsetLeft = nextTag.offsetLeft + nextTag.offsetWidth + tagAndTagSpacing;
// the tag's offsetLeft before of prevTag
const beforePrevTagOffsetLeft = prevTag.offsetLeft - tagAndTagSpacing;
if (
afterNextTagOffsetLeft >
$scrollWrapper.scrollLeft + $containerWidth
) {
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth;
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft;
}
}
}
另外,Vue router / element 项目重复点击路由报错,一般可参考https://www.cnblogs.com/dhui/p/13329316.html
我的写在路由守卫里面,也当个参考吧
// 各个项目的获取VueRouter的方法可能不一样,用的时候要灵活转换,我的项目是app.router,且使用了
// constructor才获取原型。
// 获取原型对象上的push函数
const originalPush = app.router.constructor.prototype.push;
// 修改原型对象中的push方法
app.router.constructor.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err);
};