vuetify实现Tab多标签栏,引发的router-link/事件机制问题

写在前头

由于搭建后台管理系统,国内多采用侧边栏+多标签切换页面的方式,故在实现中同样打算做一个多标签页的组件。

↓↓↓↓↓这玩意就是标签栏,我个人习惯称为tabs

示例图

需求描述

  • 点击侧边栏的某个item,判断该页面是否已经打开过

    • 没打开过:

      • vue-router自动载入组件,进入页面
      • 我们代码控制,在tabs的数组添加当前新增的这个页面的路由信息
    • 打开过,切换到对应的tab-item和页面
  • 点击不同的tab-item实现,页面的切换(这一步是vue-router自动完成的)
  • 每个tab-item可以单独关闭(首页不可关闭)
  • 右键tabs栏目,显示context-menu

    • 可关闭当前:同直接在tab-item上关闭
    • 关闭其他:保留当前页和首页
    • 关闭全部:保留首页
  • 默认关闭当前tab-item和对应的页面后,自动跳到前一个tab-item和页面

遇到的问题

这里暂时记录当前遇到的问题,后续若有新坑,再补录。。

pppp.jpeg

关闭当前tab-item

在基本实现了点击sidebar-item打开页面,并在tabs数组中添加新的项后,开始做关闭当前tab-item的功能,但是遇到了坑(灬ꈍ ꈍ灬)。。。

实现思路:

  • watch $route的变化,如果新增的tab-item在tabs数组(保存在vuex中)中不存在,就addTabItem()
  • 点击tab-item的关闭按钮时,首先判断关闭的tab-item是不是当前的路由
  • 如果是:

    • 从tabs的数组里删除掉当前的tab-item
    • 判断前一个tab-item是否存在
    • 如果存在就router.push到前一个tab-item
  • 如果不是:

    • 直接从tabs数组里删除掉那个tab-item

理想的结果:

  • 依次点击t1、t2、t3、t4,分别打开对应的页面,并在tabs上增加tab-item
  • 点击tab-item[t4]的关闭按钮,tabs栏目变为[t1,t2,t3],页面自动更新到t3对应的页面

实际上:

  • 点击tab-item[t4]的关闭按钮
  • 地址栏一瞬间跳到了t3对应的路由
  • 紧接着又跳回了t4对应的路由
  • watchroute的两次变化,且在第二的变化中重新在tabs的数组中新增了t4
  • 最终tabs[t1,t2,t3,t4],死循环...

排查思路

  • 首先想,会不会是代码逻辑的问题,反复确认,并单独写了个简化版的demo后,确定逻辑没有问题
  • 然后想到会不会是vuetify的tabs组件有一些内部的逻辑导致的

    • google搜索了一下,没有搜到相关问题(主要怀疑在optional这个属性)
    • 然后又去别人的项目中看了一下,同样使用的tabs也没有问题
  • 在参考品别人项目的时候,看到他们都是讲逻辑卸载vuex的action

    • 这时候我想 难道是我直接调用mutation出现的问题?
    • 虽说action支持异步,mutation只能是同步;但是我的router.push逻辑就是写在mutation删除当前tab-item之后执行的啊,不可能出现问题啊
  • 然后想会不会是我点击关闭按钮的时候,又触发了tab-item的点击(close按钮是包裹在tab标签里),事件向上冒泡导致重新载入了当前页呢?

    • 然后我将关闭当前tab-item按钮的点击事件改为@click.stop="onTabClose"
    • 发现然并卵
    • 就排除了这种可能
  • 最后,在不停的对照别人的项目过程中,发现别人的点击事件是@click.stop.prevent="onTabClose"

    • 尝试着增加了.prevent
    • 果然好了,卧槽!!!!!

心里顿时一万个草尼玛飘过~~~

456.jpg

在骂自己为什么不多好好看几遍文档的时候,突然意识到,这TM概念我其实知道啊,但是.prevent不是阻止事件默认行为的么,劳资实在想不到在这用啊。。。。。。


本着人道主义精神,不能光骂娘,不解决问题啊,于是有了如下:

拨开云雾见光明:

  • 首先,打开了浏览器调试控制台,通过Vue-DevToos发现,Vuetify的Tab本质上就是一个router-link

image.png

  • router-link的咋就导致出现问题了呢?直接一步到位看看生成的dom是啥吧

image.png

  • 这个是意料之中,就是生成一个a标签,然后在标签内包裹着关闭按钮
  • 那么问题看样子就出在这了,既然通过.prevent取消事件的默认行为来解决问题,那指定是a标签的默认行为不守妇道了
  • google了一下,a标签及其子元素,默认的行为就是跳转进入他的href属性指向的链接
  • 所以为了一探究竟,专门写了下面这个demo:












a标签事件测试









这是外层





  




小结

  • .stop确实是阻止了冒泡
  • 但是本质上tab内部包裹了一个router-link(其本质是个a标签)
  • 所以虽然阻止了冒泡,但是a标签的默认行为是打开href链接
  • 即使阻止了内部的冒泡,也然并卵
  • 所以最重要的是阻止a标签的默认行为

qqqqqqq.jpeg

你说谁TM能想到啊,吃一堑长一智把,以后再遇到类似场景的问题,一定要得多注意!!!

写在结尾

  • 这个问题,折磨我两天半了,终于也算了却了一桩心愿。。
  • 我这个后端临时干前端,果然是遭受了慢慢的恶意
  • 不过还是怨自己没有扎实的前端基本功,后面一定得好好系统学习一下前端知识了
  • 以上。

你可能感兴趣的:(vuetify,vue-router,javascript)