Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页

在后台管理系统页面中一般都会有导航栏标签这一功能,它可以让我们点击过的菜单以 tab 标签栏的形式展现出来,同时右键标签可以展示刷新页面,关闭当前,关闭其它,全部关闭选项,如下图所示

Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页
image.png

本篇文章将介绍导航栏标签的具体实现

新增标签

elementplus 为我们提供了 Tag 组件,我们可以直接使用

首先在全局状态管理器store/index.ts中定义一个 state:navTags 用于存放点击过的标签数据,这些数据包含的字段包括菜单名name以及跳转路由path,同时里面默认添加一个首页的标签。还需要定义一个添加标签的函数放到 actions 中

Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页
image.png

当点击菜单的时候需要在 navTags 新增一条标签数据,因此可以在路由守卫中调用 addTags 函数

//router/index.ts
router.beforeEach(async (to, from, next) => {
  //.....
  if (homeStore.menuList.length) {
   //....
    homeStore.addTags({ name: to.name as string, path: to.path });

    next();
    return;
  }
 ....

  next({ ...to, replacetrue });
});

export default router;

然后在 navbar 中使用 tag 组件,同时添加一些样式

Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页
image.png

这里有一个属性 effect,可以设置标签主题,当当前标签的 path 和当前页面路由 path 一样的话就给它设置为dark主题。获取当前页面的 path 其实很简单,在navbar.vue中监听路由变化即可

Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页
image.png

此时点击菜单的时候我们已经可以将标签一个个添加上去了,此时我们还需要让标签被点击然后跳转到对应页面

const handelTo = (item: any) => {
  router.push(item.path);
};

删除标签

Tag 组件可以设置 closable 定义一个标签是否可移除,同时提供一个点击 x 的 close 事件,我们可以在这个事件中删除当前标签在navTags中的数据,这里我们还需要判断删除的是不是当前页面,如果是的话则还需要跳转到最后一个标签选项

<el-tag
  v-for="(item, index) in homeStore.navTags"
  @click="handelTo(item)"
  :key="item.name"
  class="ml-2 cursor-pointer flex-shrink-0"
  :effect="currentPath === item.path ? 'dark' : ''"
  type="primary"
  :closable="item.path != '/'"
  @close="handleClose(index, item.path)"
>
          {{ item.name }}
        </el-tag>
const handleClose = (index: number, path: string) => {
  homeStore.navTags.splice(index, 1);
  //判断是否为当前页面,如果是则跳转至最后一个标签页
  if (path === currentPath.value) {
    const length = homeStore.navTags.length;
    length && router.push(homeStore.navTags[length - 1].path);
  }
};

到这里导航标签功能基本完成,接下来来实现点击鼠标右键出现刷新页面,关闭当前等选项功能

右键列表功能

在 src/component 中新增一个 tagsview 组件用于实现右键列表功能

<template>
  <div class="bg-white shadow-lg rounded-md text-[14px] overflow-hidden cursor-pointer">
    <div class="p-1 hover:bg-[#E0E0E0] flex items-center" @click="refresh">
      <el-icon>
        <Refresh />
      </el-icon><span>刷新页面</span>
    </div>
    <div class="p-1 hover:bg-[#E0E0E0] flex items-center" @click="emits('closeCur')">
      <el-icon>
        <CloseBold />
      </el-icon><span>关闭当前</span>
    </div>
    <div class="p-1 hover:bg-[#E0E0E0] flex items-center" @click="closeOtherTags">
      <el-icon>
        <Close />
      </el-icon><span>关闭其它</span>
    </div>
    <div class="p-1 hover:bg-[#E0E0E0] flex items-center" @click="closeAllTags">
      <el-icon>
        <Close />
      </el-icon><span>全部关闭</span>
    </div>
  </div>

</template>

<script lang="ts" setup>
import home from "../
./../store";
import { useRouter } from "
vue-router";
const router = useRouter();
const homeStore = home();
type Props = {
  tag: {
    path: string;
    name: string;
  };
};

const props = defineProps<Props>();
type Emits = {
  (e: "
closeCur"): void;
  (e: "
closeTagView"): void;
};
const emits = defineEmits<Emits>();
//刷新页面
const refresh = () => {
  window.location.reload();
};
//关闭其它
const closeOtherTags = () => {
  homeStore.$patch({
    navTags: [{ name: "
首页", path: "/" }, props.tag],
  });
  router.push(props.tag.path);
  emits("
closeTagView");
};
//关闭所有
const closeAllTags = () => {
  homeStore.$patch({
    navTags: [{ name: "
首页", path: "/" }],
  });
  router.push("
/");
  emits("
closeTagView");
};
</script>

vue 中鼠标右击事件可以使用@contextmenu,同时我们需要知道当前点击的位置,然后根据当前位置定位,所以可以将事件参数$event传入,并且要将当前点击的标签参数传入

<el-tag
  @contextmenu.prevent="openMenu($event, item.path)"
  v-for="(item, index) in homeStore.navTags"
  @click="handelTo(item)"
  :key="item.name"
  class="ml-2 cursor-pointer flex-shrink-0"
  :effect="currentPath === item.path ? 'dark' : ''"
  type="primary"
  :closable="item.path != '/'"
  @close="handleClose(index, item.path)"
>
          {{ item.name }}
          <teleport to="body">
            <tagsview v-if="isTagView && currentTagPath === item.path" @closeTagView="isTagView = false" :tag="item"
              class="w-[100px] fixed" :style="tagViewStyle" @closeCur="handleClose(index, item.path)" />

          </teleport>
        </
el-tag>

这里我们可以通过$event中的clientXclientY获取到当前点击位置距离浏览器窗口的坐标,即固定定位(fixed),刚好可以将列表定位到这里。 同时添加一个document的点击事件用于关闭列表

const listener = () => {
  isTagView.value = false;
  document.removeEventListener("click", listener);
};
const tagViewStyle = ref({});
const openMenu = (e: any, path: string) => {
  isTagView.value = true;
  document.addEventListener("click", listener);

  tagViewStyle.value = {
    left: e.clientX + "px",
    top: e.clientY + "px",
  };
};

到这里简单的右键列表功能就已经实现了

Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页
image.png

[代码地址]留言获取


原文始发于微信公众号(web前端进阶):Vue + Element Plus 实现权限管理系统(六):实现导航栏标签页

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/232199.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!