vue.js 怎么将路由渲染到新生成的路由命名视图上面?

新手上路,请多包涵

clipboard.png
点击左边的菜单栏,右边会新增一个tab,然后希望将左边菜单栏的路由解析出口指定到新生成的tab上面,这样就能保留多个tab标签内容了,但是不知道怎么实现,求大神帮忙!

阅读 1.4k
1 个回答

tagNav
不知道楼主的意思是不是想要我图中的效果。
点击左侧菜单栏,在右侧头部显示当前栏目的标签按钮。当标签栏占满,会出现自动滚动到可见区域。
这种实现也比较简单。下面是我实现的原理
左侧菜单leftbar页面加子菜单navitem页面省略,如需要请留言。
这里面重点讲tagNav页面的实现

<template>
  <div class="tag-nav">
    <scroll-bar ref="scrollBar">
      <router-link
        ref="tag"
        class="tag-nav-item"
        :class="isActive(item) ? 'cur' : ''"
        v-for="(item, index) in tagNavList"
        :to="item.path"
        :key="index"
      >
        {{item.title}}
        <span class="el-icon-close" @click.prevent.stop="closeTheTag(item, index)"></span>
      </router-link>
    </scroll-bar>
  </div>
</template>

<script>
import ScrollBar from '@/components/ScrollBar';

export default {
  data() {
    return {
      defaultPage: '/main',
    };
  },
  computed: {
    tagNavList() {
      //console.log(this)
      //console.log(this.$store)
      //console.log(this.$store.state.tagNav.openedPageList);
      return this.$store.state.tagNav.openedPageList;
    },
  },
  mounted() {
    // 首次加载时将默认页面加入缓存
    this.addTagNav();
  },
  watch: {
    $route() {
      this.addTagNav();
      this.scrollToCurTag();
    },
  },
  methods: {
    addTagNav() {
      // 如果需要缓存则必须使用组件自身的name,而不是router的name
      this.$store.commit('tagNav/addTagNav', {
        //name: this.$router.getMatchedComponents()[1].name,
        name: this.$route.name,
        path: this.$route.path,
        title: this.$route.meta.title,
      });
    },
    isActive(item) {
      return item.path === this.$route.path;
    },
    closeTheTag(item, index) {
      // 当关闭当前页面的Tag时,则自动加载前一个Tag所属的页面
      // 如果没有前一个Tag,则加载默认页面
      this.$store.commit('tagNav/removeTagNav', item);
      if (this.$route.path == item.path) {
        if (index) {
          this.$router.push(this.tagNavList[index - 1].path);
        } else {
          this.$router.push(this.defaultPage);
          if (this.$route.path == this.defaultPage) {
            this.addTagNav();
          }
        }
      }
    },
    scrollToCurTag() {
      this.$nextTick(() => {
        for (let item of this.$refs.tag) {
          if (item.to === this.$route.path) {
            this.$refs.scrollBar.scrollToCurTag(item.$el);
            break;
          }
        }
      });
    },
  },
  components: { ScrollBar },
};
</script>

<style lang="less" scoped>
.tag-nav {
  position: absolute;
  top: 0;
  width: 100%;
  height: 53px;
  padding: 10px;
  background: #fff;
  border-bottom: 1px solid #ddd;
  box-shadow: 0 1px 2px #f2f2f2;
  box-sizing: border-box;
  .tag-nav-item {
    display: inline-block;
    position: relative;
    height: 30px;
    line-height: 30px;
    padding: 0 10px;
    margin-right: 10px;
    border: 1px solid rgba(82, 186, 181, 0.2);
    border-radius: 4px;
    background-color: rgba(82, 186, 181, 0.1);
    text-decoration: none;
    span {
      width: 16px;
      height: 16px;
      line-height: 16px;
      border-radius: 50%;
      text-align: center;
      vertical-align: middle;
      transition: all 0.3s ease;
      -webkit-transform-origin: 100% 50%;
      -ms-transform-origin: 100% 50%;
      transform-origin: 100% 50%;
      font-size: 12px;
      color: #52bab5;
    }
  }
  .cur {
    background-color: #52bab5;
    color: #fff;
    span {
      color: #fff;
    }
  }
}
</style>

其中标签占满的时会自动向左滚动,让当前标签可见。
ScrollBar组件

<template>
  <div class="scroll-wrap" ref="scrollWrap" @wheel.prevent="scroll">
    <div class="scroll-cont" ref="scrollCont" :style="{left: left + 'px'}">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      left: 0,
      wheelSpeed: 30,
    };
  },
  mounted() {},
  methods: {
    scroll(e) {
      const scrollWrapWidth = this.$refs.scrollWrap.offsetWidth;
      const scrollContWidth = this.$refs.scrollCont.offsetWidth;
      if (scrollContWidth > scrollWrapWidth) {
        // 统一不同浏览器下wheel事件的滚动值
        // chrome/FF/Edge/IE11/IE10/IE9
        // e.deltaY > 0 即鼠标滚轮向下滚动,则该条向右滚动,left值变负
        const scrollSpace =
          e.deltaY > 0 ? -1 * this.wheelSpeed : this.wheelSpeed;
        if (e.deltaY > 0) {
          if (
            Math.abs(this.left + scrollSpace) <=
            scrollContWidth - scrollWrapWidth
          ) {
            this.left += scrollSpace;
          }
        } else {
          if (this.left + scrollSpace < 0) {
            this.left += scrollSpace;
          } else {
            this.left = 0;
          }
        }
      } else {
        return;
      }
    },
    scrollToCurTag(tar) {
      const scrollWrapWidth = this.$refs.scrollWrap.offsetWidth;
      const tarWidth = tar.offsetWidth;
      const tarLeft = tar.offsetLeft;

      if (tarLeft < -1 * this.left) {
        // 激活的标签导航在左边
        this.left = -tarLeft;
      } else if (tarLeft + tarWidth > scrollWrapWidth) {
        // 激活的标签导航在右边
        this.left = -(tarLeft + tarWidth - scrollWrapWidth);
      }
    },
  },
};
</script>
<style scoped>
.scroll-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  white-space: nowrap;
  overflow: hidden;
}
.scroll-cont {
  position: absolute;
  transition: all 0.3s ease;
}
</style>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题