前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BuildAdmin11:弹出框的弹出和隐藏以及标签禁用的小skill

BuildAdmin11:弹出框的弹出和隐藏以及标签禁用的小skill

原创
作者头像
叫我阿柒啊
修改2024-06-11 17:15:17
1950
修改2024-06-11 17:15:17
举报

前言

在上篇文章中写了如何实现弹出框,最后也留下了一个问题:在tab栏中点击哪里,弹出框就出现在哪里,这个是怎么实现的?

在此之前我们先思考:在浏览器中右键,通常会出现什么?

prevent和$event

在这里我们的需求是,在右键tab导航栏时,弹出选项框。但实际上在右键点击时,会弹出浏览器菜单。

我们之前在实现tab的关闭时,讲了 @click.stop 阻止点击事件冒泡。这里为了右键时不弹出浏览器的菜单,使用 @contextmenu.prevent

click指的是左键点击事件,contextmenu指的是右键点击事件。prevent的作用就是阻止原生事件,这里指的就是右键不再弹出浏览器菜单,而是触发绑定的新事件。我们看看新事件的方法:

代码语言:javascript
复制
@contextmenu.prevent="onContextmenu(item, $event)"

在tab的父标签中绑定了右键事件,阻止右键菜单并且调用onContextmenu方法。

onContextmenu传入了两个参数,item指得就是路由,这样就可以将tab与弹出框的标签绑定;vue中通过v-on绑定事件处理函数, $event 参数可以访问原生事件对象,其中包含了事件发生时的所有信息和参数,在这里指的是右键点击事件,我们看一下它的属性。

其中clientXclientY是鼠标事件触发时的鼠标相对于浏览器窗口的位置,通过这两个属性就可以解决开头提到的在tab栏中点击哪里,弹出框就出现在哪里这个问题。

我们看看onContextmenu实现逻辑。

onContextmenu

在tabs.vue中,一共为弹出框一共定义了五个功能标签。

代码语言:javascript
复制
contextmenuItems: [
    {name: 'refresh', label: '重新加载', icon: 'fa fa-refresh'},
    {name: 'close', label: '关闭标签', icon: 'fa fa-times'},
    {name: 'fullScreen', label: '当前标签全屏', icon: 'el-icon-FullScreen'},
    {name: 'closeOther', label: '关闭其他标签', icon: 'fa fa-minus'},
    {name: 'closeAll', label: '关闭全部标签', icon: 'fa fa-stop'},
],

onContextmenu没有实现上面的功能,只是作为一个入口,将tab对应的router和鼠标坐标传递给弹出框组件的contextmenuRef函数。

代码语言:javascript
复制
const onContextmenu = (menu: RouteLocationNormalized, event: MouseEvent) => {
    // 禁用刷新,只有打开的tab才能刷新
    state.contextmenuItems[0].disabled = route.path !== menu.path
    // 当只有一个tab时,禁用关闭其他和关闭全部
    state.contextmenuItems[4].disabled = state.contextmenuItems[3].disabled = navTabs.state.tabsView.length == 1 ? true : false
    const {clientX, clientY} = event
    contextmenuRef.value.onShowContextmenu(menu, {
        x: clientX,
        y: clientY
    })
}

contextmenuRef是弹出框组件的引用,使用ref实现的。

代码语言:html
复制
 <Contextmenu ref="contextmenuRef" :items="state.contextmenuItems" @contextmenuItemClick="onContextmenuItem"/>

1. 实现弹出框坐标位置

onShowContextmenu是在弹出框组件中定义的,接收tabs中onContextmenu传入的路由、坐标参数。onShowContextmenu只有三行代码。

代码语言:javascript
复制
const onShowContextmenu = (menu: RouteLocationNormalized, axis: Axis) => {
    state.menu = menu
    state.axis = axis
    state.show = true
}

将路由、坐标赋值给state变量,设置show为ture。

Axis是自定义的接口,里面只有x、y两个属性。弹出框使用v-show绑定了show变量决定是否弹出,所以在onShowContextmenu被调用时,将show设置为true,这样就弹出框就能展示。

而代表坐标位置的Axis变量,被弹出框的style属性(即css)绑定。

代码语言:html
复制
<div
  class="el-popper is-pure is-light el-dropdown__popper ba-contextmenu"
  :style="`top:${state.axis.y + 5}px; left:${state.axis.x - 14}px; width:${props.width}px`"
  :key="Math.random()"
  v-show="state.show"
  aria-hidden="false"
  data-popper-placement="bottom"
>

利用top和left修改弹出框的位置,就能实现在tab栏中点击哪里,弹出框就出现在哪里。

2. 弹出框关闭

在弹出框组件中,除了定义onShowContextmenu在tabs中调用,用来触发显示弹出框,还定义了onHideContextmenu用来关闭弹出框。

代码语言:javascript
复制
const onHideContextmenu = () => {
    state.show = false
}

就一行简单的代码,将show设置为false即可。那么,想一下弹出框在什么时候会隐藏呢?是不是鼠标左键点击弹出框以外的位置就会隐藏。

代码语言:javascript
复制
import {useEventListener} from '@vueuse/core'

onMounted(() => {
    useEventListener(document, 'click', onHideContextmenu)
})

使用的是 @vueuse/coreuseEventListener实现的,用来监听document的click事件,监听到则触发onHideContextmenu来关闭弹出框。

3. 标签禁用

disabled是在tabs.vue中定义contextmenuItems时设定的属性,在渲染弹出框的时候,就会使用此属性,来判断在某些情况下哪些标签会被禁用。

标签禁用的情况有两种:

  1. 只有当前打开的tab才能刷新,此刻如果右键点击其他tab,显示弹出框的时候要禁用
  2. 当只有一个tab时,关闭其他页面、关闭所有页面功能要禁用

所以在onContextMenu中添加下面两行代码,每次弹出框弹出之前都会先完成5个标签disabled属性的初始化:

代码语言:javascript
复制
// 禁用刷新,只有打开的tab才能刷新
state.contextmenuItems[0].disabled = route.path !== menu.path && navTabs.state.tabsView.length > 1
// 当只有一个tab时,禁用关闭其他和关闭全部
state.contextmenuItems[4].disabled = state.contextmenuItems[3].disabled = navTabs.state.tabsView.length == 1 ? true : false

tabsView是一个存放路由的列表,tabs的渲染就是遍历tabsView。这里加一个大于1的判断原因是:在首次访问时,是通过getFirstRoute获取路由渲染的第一个tab(控制台),这里没有触发route.push跳转,route.path与控制台的path就不相等,重新加载就会被禁用,如果这里要加length判断,避免禁用。下面是没有加length判断的情况:

BuildAdmin在实现重新加载禁用时,就没做length的判断。在第七篇写tab及滑动块实现时,因为一些技术问题,就用了和BuildAdmin不一样的方法进行实现的。所以后面涉及tab的部分需要做一些适当的修改。

在弹出框组件渲染标签时,将class与disabled绑定。

代码语言:html
复制
<li class="el-dropdown-menu__item" :class="item.disabled ? 'is-disabled' : ''" >

这里使用了三目运算符,当class为is-disabled时,ElementPlus会自动渲染css。

ElementPlus自动将cursor设置为not-allowedcolor设置为内部定义的禁用颜色变量 --el-text-color-disabled( #c0c4cc) ,这样就实现了标签禁用。

结语

本篇文章主要讲了弹出框的两个知识点:弹出位置和标签禁用,都是对ElementPlus和vue简单的使用。

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • prevent和$event
  • onContextmenu
    • 1. 实现弹出框坐标位置
      • 2. 弹出框关闭
        • 3. 标签禁用
        • 结语
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档