Vue顶部tags浏览历史的实现

目录
  • 废话
  • 实现的功能
  • 正文
  • 重点

废话

demo预览

实现的功能

默认有首页,不能关闭

点击路由菜单,判断有无存在,没有就添加,有就定位到上面

点击跳转,点击X可关闭

关闭当前页,自动跳到下一个tag页面

如果当前页在最后一个,默认跳到上一个tag页面

右键菜单,刷新,关闭右侧,关闭所有

动态判断tags长多,放不下时,出现左右两侧按钮,减少时自动消失

动态判断窗口放大缩小,自动判断有无左右两侧按钮

正文

不用任何vuex,乱七八糟的方法,全在一个文件,粘贴即用

放到你想要的位置即可(此demo,放在了面包屑上面)

先安装 (监听某dom元素大小的包)

npm install element-resize-detector

tags.vue

<template>
  <div>
    <div class="tags">
      <!-- 左箭头 -->
      <div
        class="arrow arrow_left"
        v-show="arrowVisible"
        @click="handleClickToLeft"
      >
        <i class="el-icon-arrow-left"></i>
      </div>
      <!-- 标签内容 -->
      <div class="tags_content" ref="box">
        <span ref="tags">
          <el-tag
            v-for="(tag, index) in tags"
            :key="tag.name"
            :class="[active == index ? 'active top_tags' : 'top_tags']"
            effect="dark"
            :closable="tag.name != 'Firstpage1'"
            @close="handleClose(index, tag)"
            @click="clickTag(index, tag)"
            @contextmenu.native.prevent="handleClickContextMenu(index, tag)"
          >
            {{ $t("router." + tag.name) }}
          </el-tag>
        </span>
      </div>
      <!-- 右箭头 -->
      <div
        class="arrow arrow_right"
        v-show="arrowVisible"
        @click="handleClickToRight"
      >
        <i class="el-icon-arrow-right"></i>
      </div>
    </div>
    <!-- 右键菜单 -->
    <ul
      v-show="contextMenu.isShow"
      :style="{ left: contextMenu.menuLeft, top: '96px' }"
      class="el-dropdown-menu el-popper"
      x-placement="bottom-end"
    >
      <li
        v-if="this.active == this.contextMenu.index"
        class="el-dropdown-menu__item"
        @click="refresh"
      >
        刷新
      </li>
      <li class="el-dropdown-menu__item" @click="closeRightTag">
        关闭右侧
      </li>
      <li class="el-dropdown-menu__item" @click="closeOtherTag">
        关闭其它
      </li>
      <div x-arrow="" class="popper__arrow" style="left: 44px;"></div>
    </ul>
  </div>
</template>

<script>
import elementResizeDetectorMaker from "element-resize-detector";
export default {
  data() {
    return {
      // 是否有箭头
      arrowVisible: true,
      // 点击次数
      num: 0,
      active: 0,
      tags: [],
      // 右键的元素
      contextMenu: {
        index: 0,
        tag: {},
        menuLeft: 0,
        isShow: false
      }
    };
  },
  watch: {
    $route() {
      this.getThisPage();
    },
    tags() {
      this.listenFun(this.$refs.tags, "tags");
    }
  },
  mounted() {
    this.listenFun(this.$refs.box, "box");
    var that = this;
    document.addEventListener("click", function(e) {
      that.contextMenu.isShow = false;
    });
  },
  methods: {
    // 监听可视区域宽,浏览器窗口大小改变执行
    listenFun(monitor, dom) {
      let boxWidth = this.$refs.box.offsetWidth,
        tagsWidth = this.$refs.tags.offsetWidth,
        erd = elementResizeDetectorMaker();
      erd.listenTo(monitor, ele => {
        this.$nextTick(() => {
          if (
            (dom == "box" && ele.offsetWidth >= tagsWidth) ||
            (dom == "tags" && ele.offsetWidth <= boxWidth)
          ) {
            this.arrowVisible = false;
            this.$refs.box.style.paddingLeft = "16px";
            this.$refs.box.style.paddingRight = "16px";
            this.$refs.box.style.transform = "TranslateX(0px)";
            this.num = 0;
          } else {
            this.arrowVisible = true;
            this.$refs.box.style.paddingLeft = "56px";
            this.$refs.box.style.paddingRight = "56px";
          }
        });
      });
    },
    // 判断当前页
    getThisPage() {
      let currentPgae = this.$route;
      // 判断tags里是否有当前页面
      var index = this.tags.findIndex(tag => tag.name == currentPgae.name);
      if (index == -1) {
        this.tags.push({
          name: currentPgae.name,
          path: currentPgae.path
        });
      }
      // 当前选择页
      this.active = this.tags.findIndex(tag => tag.name == currentPgae.name);
    },
    // 关闭标签
    handleClose(index, tag) {
      this.tags.splice(this.tags.indexOf(tag), 1);
      if (index == this.tags.length) {
        this.active = index - 1;
        this.$router.push(this.tags[index - 1].path);
      } else {
        this.$router.push(this.tags[index].path);
      }
    },
    // 点击标签
    clickTag(index, tag) {
      this.active = index;
      this.$router.push(tag.path);
    },
    // 左侧按钮
    handleClickToLeft() {
      if (this.num > 0) {
        this.num--;
        this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`;
      }
    },
    // 右侧按钮
    handleClickToRight() {
      // 最后一个标签右测距离浏览器左侧距离
      let lastChild = document
        .querySelectorAll(".top_tags")
        [this.tags.length - 1].getBoundingClientRect().right;
      // 可视窗口的宽
      let bodyWidth = document.body.offsetWidth;
      // 右侧箭头48+右侧边距16
      if (bodyWidth - lastChild <= 64) {
        this.num++;
        this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`;
      }
    },
    // 右键
    handleClickContextMenu(index, tag) {
      this.contextMenu.isShow = true;
      this.contextMenu.index = index;
      this.contextMenu.tag = tag;
      let isTag = document
        .querySelectorAll(".top_tags")
        [index].getBoundingClientRect();
      this.contextMenu.menuLeft = isTag.left - 48 + isTag.width / 2 + "px";
    },
    // 刷新
    refresh() {
      this.$router.go(0);
    },
    // 关闭其他
    closeOtherTag() {
      let tagsLin = this.tags.length,
        { index, tag, menuLeft } = this.contextMenu;
      if (index != 0) {
        this.tags = [
          {
            name: "Firstpage1",
            path: "/First/page1"
          },
          {
            name: tag.name,
            path: tag.path
          }
        ];
      } else {
        this.tags = [
          {
            name: "Firstpage1",
            path: "/First/page1"
          }
        ];
      }
      this.active = index;
      this.$router.push(tag.path);
    },
    // 关闭右侧
    closeRightTag() {
      let tagsLin = this.tags.length,
        { index, tag, menuLeft } = this.contextMenu;
      this.tags.splice(index + 1, tagsLin - index);
      this.active = index;
      this.$router.push(tag.path);
    }
  },
  created() {
    // 监听页面刷新
    window.addEventListener("beforeunload", e => {
      localStorage.setItem(
        "tagInfo",
        JSON.stringify({
          active: this.active,
          tags: this.tags
        })
      );
    });
    let tagInfo = localStorage.getItem("tagInfo")
      ? JSON.parse(localStorage.getItem("tagInfo"))
      : {
          active: 0,
          tags: [
            {
              name: "Firstpage1",
              path: "/First/page1"
            }
          ]
        };
    this.active = tagInfo.active;
    this.tags = tagInfo.tags;
  }
};
</script>
<style lang="less" scoped>
/deep/.el-tag--dark {
  border-color: transparent;
}
/deep/.el-tag--dark .el-tag__close {
  color: #86909c;
  font-size: 16px;
}
/deep/.el-tag--dark .el-tag__close:hover {
  background: #e7eaf0;
}
.tags {
  position: relative;
  overflow: hidden;
  .arrow {
    width: 48px;
    text-align: center;
    cursor: pointer;
    background: #fff;
    position: absolute;
    z-index: 1;
    &_left {
      left: 0;
      top: 0;
    }
    &_right {
      right: 0;
      top: 0;
    }
  }
  &_content {
    transition: 0.3s;
    white-space: nowrap;
    // padding: 0 16px;
  }
  .top_tags {
    margin-right: 8px;
    cursor: pointer;
    background: #fff;
    font-size: 12px;
    font-weight: 400;
    color: #1d2129;
  }
  .top_tags:hover,
  .active,
  .arrow:hover {
    background: #e7eaf0;
  }
}
</style>

重点

需要修改的地方

currentPgae.name 是路由结构的name,判断有无存在,没有就添加,有就定位到上面,根据项目修改

监听刷新时,去本地存储 tags 和 当前页面的active,Ftistpage1 改成自己的首页即可 

到此这篇关于Vue顶部tags浏览历史的实现的文章就介绍到这了,更多相关Vue顶部tags浏览历史内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue实现顶部菜单栏

    vue实现顶部菜单栏,同一个页面两个菜单按钮之间的切换 先看展示结果: 点击第一个按钮,显示内容1 点击第二个按钮,展示内容2 下面上源码:注意哦,一定要代码规划,别学我(⊙o⊙) <template> <div> <div class="tab-content"> <div class="tab-content1" @click="cur=1" :class="{active:cur==1}&

  • vue实现移动端返回顶部

    本文实例为大家分享了vue实现移动端返回顶部的具体代码,供大家参考,具体内容如下 HTML: <template> <div class="home"> <div v-for="ys in 100" :key="ys"> <p>1</p> </div> <div @click="back" class="back1" v-show

  • vue搜索页开发实例代码详解(热门搜索,历史搜索,淘宝接口演示)

    完整效果演示 首先完成这个伪搜索框 src/components/search/index.vue (通用搜索框组件) <template> <div class="mine-search-box-wrapper"> <i class="iconfont icon-search"></i> <div class="mine-search-box" v-if="fake"&g

  • vue实现顶部左右滑动导航

    日常开发中经常用到导航这些东西,写篇文章记录下.该导航实现为点击末尾/起首位置,导航自动滑动出下一项的效果. 思路:判断当前点击项,相对与屏幕的位置,若点击的位置,满足可移动的限制,进行自动滑动处理. 实现如下: vue <template> <div class="debug-index-page"> <div class="tab-layout" id="scroller"> <ul v-for=&q

  • vuex实现历史记录的示例代码

    最近自研着一个可视化操作平台,其中涉及到用户操作后可撤销或重做,在网上搜了一些解决思路,完善自己所设想的解决思路. 历史记录需求的要点 可存储在 localStorage 中 可多次撤销或多次重做 点击列表中的一项,将历史倒退或前进至指定位置 看似简单的需求,在基础建设设计上的错误,亦会在未来导致更多的工作量.所以结合上面两点的要求,发现 vuex 的基本思路非常适合完成这个需求,redux 同样. 实现思路 此项目用了 typescript 来加强代码的严谨性,方便日后维护,大家简单看个思路.

  • Vue 实现输入框新增搜索历史记录功能

    vue实现搜索显示历史搜索记录,采用插件-good-storage 安装插件    npm install good-storage -S 在本地新建cache.js文件,该文件是关于本地存储的逻辑处理(缓存到本地的数据最大缓存15条,并且新的插入在第一位,首先得到当前的存储数据情况,将关键字存到数组中,判断如果数组中有相同的数据,则把重复的数据删除,将新的关键字存入到前面) cache.js 文件中的代码如下 /*把搜索的结果保存下来*/ /*用export把方法暴露出来*/ /*定义存储搜索

  • Vue切换组件实现返回后不重置数据,保留历史设置操作

    版权 1.<router-view ></router-view> 外层包围<keep-alive> </keep-alive> keep-alive作用将组件实例缓存下来 <keep-alive> <router-view></router-view> </keep-alive> 2.清除组件缓存 使用keep-alive 的 exclude="组件名" 属性 <keep-alive

  • Vue顶部tags浏览历史的实现

    目录 废话 实现的功能 正文 重点 废话 demo预览 实现的功能 默认有首页,不能关闭 点击路由菜单,判断有无存在,没有就添加,有就定位到上面 点击跳转,点击X可关闭 关闭当前页,自动跳到下一个tag页面 如果当前页在最后一个,默认跳到上一个tag页面 右键菜单,刷新,关闭右侧,关闭所有 动态判断tags长多,放不下时,出现左右两侧按钮,减少时自动消失 动态判断窗口放大缩小,自动判断有无左右两侧按钮 正文 不用任何vuex,乱七八糟的方法,全在一个文件,粘贴即用 放到你想要的位置即可(此dem

  • vue顶部菜单栏实现小结

    参考: 使用element-ui的el-menu导航选中后刷新页面保持当前选中状态 效果图1: <!--home--> <template> <div class="homeContainer"> <div style=" display: flex; height: 60px; line-height: 60px; align-items: center; " > <div style=" displ

  • jquery使用Cookie和JSON记录用户最近浏览历史

    在一些电商网站,有"商品浏览历史记录"这一功能,一些视频类.小说类的网站也能记录用户最近的浏览历史.本文将使用Cookie以及JSON来讲解如何实现这一功能. Cookie可以用来记录客户端用户ID.密码.浏览过的网页.停留的时间等信息,jQuery提供了一个cookie插件,能非常方便的读写cookie信息. 基本流程: 1.获取文章详情页面文章的标题和页面地址: 2.获取浏览历史cookie信息,判断如果浏览历史的cookie中已经存在当前文章的浏览记录,则不进行任何操作: 3.如

  • thinkphp浏览历史功能实现方法

    本文实例讲述了thinkphp浏览历史功能实现方法,分享给大家供大家参考.具体实现方法分析如下: 历史浏览功能都是使用了cookie功能记录用户信息放到了本地了,这样我们只要读取存储在cookies中的值就可以了,下面来给大家介绍一个基于thinkphp 实现浏览历史功能例子. 就像浏览器一样,能够记录访问了哪些页面,这样能够减少时间,下面我们实现浏览历史的功能. 1.在你需要记录浏览数据的产品或新闻页面,记录cookie需要保存的信息,例如下面这行代码,把页面ID,产品名称,价格,缩略图,网址

  • PHP实现将浏览历史页面网址保存到cookie的方法

    本文实例讲述了PHP实现将浏览历史页面网址保存到cookie的方法.分享给大家供大家参考.具体如下: 将浏览历史页面网址保存到cookie,大致的思路如下面的代码,与实际应用有些差别. 复制代码 代码如下: <?php /*******  说明:cookie只能保存字符串 本实例中,需要保存多个URL(历史访问记录),思路是先将URL数组转为字符串,然后保存,读取时,再循环读取 *******/ //先假设当前URL为:http://localhost/php/?id=1 $id = $_GET

  • vue如何清除浏览器历史栈

    目录 如何清除浏览器历史栈 问题 vue返回首页后如何清空路由 需求一:从首页点击路由到A页面 需求二:把浏览器的记录返回指定的页面 如何清除浏览器历史栈 问题 需要跳转好几个页面进行表单提交,提交完之后,跳转回首页,返回上一页,发现还可以返回上一级页面路由 //可以拿到历史记录栈,清空栈 let routeHistory=history.length-1; this.$router.go(-routeHistory); vue返回首页后如何清空路由 需求一:从首页点击路由到A页面 A页面点击路

  • javascript结合Cookies实现浏览记录历史第1/3页

    由于以前对javascript了解不够深入,一时间手足无措. 后来经过两位高手同事的指点(对这两位同事的敬仰犹如滔滔江水连绵不绝...),恍然大悟,豁然开朗 成功地完成了此功能的添加. 首先来介绍一下javascript中关于此功能的一些对象和方法: 1. window.event对象: event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生的过程中才有效. 2. event.srcElement: 表示该事件的发生源 通俗一点说也就

  • 详解vue 单页应用(spa)前端路由实现原理

    写在前面:通常 SPA 中前端路由有2种实现方式: window.history location.hash 下面就来介绍下这两种方式具体怎么实现的 一.history 1.history基本介绍 window.history 对象包含浏览器的历史,window.history 对象在编写时可不使用 window 这个前缀.history是实现SPA前端路由是一种主流方法,它有几个原始方法: history.back() - 与在浏览器点击后退按钮相同 history.forward() - 与

  • 在vue中实现嵌套页面(iframe)

    vue中嵌套iframe,将要嵌套的文件放在static下面.src可以使用相对路径,也可使用服务器根路径http:localhost:8088/- <iframe src="../../static/plusPro.html" width="1200" height="300" frameborder="0" scrolling="auto"style="position:absolute

随机推荐