关于TagsView的一些记录

参考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);
};

上一篇:Flask入门(第一个flask程序)


下一篇:RESTful 1