• Dropdown 下拉菜单实现标签页的相关操作


    Dropdown 组件是向下弹窗列表。点击或移入触电,会出现一个下拉菜单,可以在列表中进行选择,并执行相应的命令。

    二次封装对外暴露参数

    <script lang="ts" setup>
      const props = defineProps({
        // 是否确认
        popconfirm: Boolean,
        // 触发下拉的行为,默认鼠标右击触发
        trigger: {
          type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,
          default: () => {
            return ['contextmenu'];
          },
        },
        // 下拉菜单
        dropMenuList: {
          type: Array as PropType<(DropMenu & Recordable)[]>,
          default: () => [],
        },
        // 当前选中的菜单项 key 数组
        selectedKeys: {
          type: Array as PropType<string[]>,
          default: () => [],
        },
      })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    dropdown 组件

    dropdown 组件使用 ant-design-vue 库支持 overlay 插槽插入菜单列表,默认插槽插入显示信息。

    
    <template>
      <a-dropdown :trigger="trigger" v-bind="$attrs">
        <span>
          <slot>slot>
        span>
        <template #overlay>
          <a-menu :selectedKeys="selectedKeys">
            <template v-for="item in dropMenuList" :key="`${item.event}`">
              <a-menu-item
                v-bind="getAttr(item.event)"
                @click="handleClickMenu(item)"
                :disabled="item.disabled"
              >
                <Icon :icon="item.icon" v-if="item.icon" />
                <span class="ml-1">{{ item.text }}span>
              a-menu-item>
              <a-menu-divider v-if="item.divider" :key="`d-${item.event}`" />
            template>
          a-menu>
        template>
      a-dropdown>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    菜单项点击事件

    const emit = defineEmits(['menuEvent'])
    
    function handleClickMenu(item: DropMenu) {
      const { event } = item
      const menu = props.dropMenuList.find(item => item.event === event)
      emit('menuEvent', menu)
      item.onClick?.()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    useTabDropdown 的设计

    useTabDropdown 方法对外暴露属性和方法,如下:

    // src/layout/default/tabs/useTabDropdown.ts
    export function useTabDropdown(tabContentProps, getIsTabs) {
      // 获取下拉菜单
      const getDropMenuList = computed(() => {})
      // 选中菜单项
      function handleContextMenu() {}
      // 处理菜单事件
      function handleMenuEvent() {}
    
      return { getDropMenuList, handleMenuEvent, handleContextMenu }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    useTabDropdown 的实现

    import { useTabs } from '/@/hooks/web/useTabs'
    
    const getDropMenuList = computed(() => {
      const dropMenuList = [
        { icon: 'ion:reload-sharp', event: MenuEventEnum.REFRESH_PAGE, text: '重新加载', disabled: refreshDisabled, },
        { icon: 'clarity:close-line', event: MenuEventEnum.CLOSE_CURRENT, text: '关闭标签', disabled: !!meta ?.affix || disabled, divider: true, },
        { icon: 'line-md:arrow-close-left', event: MenuEventEnum.CLOSE_LEFT, text: '关闭左侧标签页', disabled: closeLeftDisabled, divider: false, },
        { icon: 'line-md:arrow-close-right', event: MenuEventEnum.CLOSE_RIGHT, text: '关闭右侧标签页', disabled: closeRightDisabled, divider: true, },
        { icon: 'dashicons:align-center', event: MenuEventEnum.CLOSE_OTHER, text: '关闭其他标签页', disabled: disabled || !isCurItem, },
        { icon: 'clarity:minus-line', event: MenuEventEnum.CLOSE_ALL, text: '关闭全部标签页', disabled: disabled, },
      ]
      return dropMenuList
    })
    
    const { refreshPage, closeAll, close, closeLeft, closeOther, closeRight } = useTabs();
    
    function handleMenuEvent(menu) {
      const { event } = menu
      switch (event) {
        case MenuEventEnum.REFRESH_PAGE:
          refreshPage();
          break;
        case MenuEventEnum.CLOSE_CURRENT:
          close(tabContentProps.tabItem);
          break;
        case MenuEventEnum.CLOSE_LEFT:
          closeLeft();
          break;
        case MenuEventEnum.CLOSE_RIGHT:
          closeRight();
          break;
        case MenuEventEnum.CLOSE_OTHER:
          closeOther();
          break;
        case MenuEventEnum.CLOSE_ALL:
          closeAll();
          break;
      }
    }
    
    function handleContextMenu(tabItem) {
      return (e) => {
        if (!tabItem) {
          return
        }
        e?.preventDefault()
        const index = tabStore.getTabList.findIndex(tab => tab.path === tabItem.path)
        // 后续可用于菜单列表 disabled 属性处理
        state.current = tabItem
        state.currentIndex = index
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    组件使用

    
    <template>
      <Dropdown
        :dropMenuList="getDropMenuList"
        :trigger="getTrigger"
        placement="bottom"
        overlayClassName="multiple-tabs__dropdown"
        @menu-event="handleMenuEvent"
      >
        <div :class="`${prefixCls}__info`" @contextmenu="handleContext" v-if="getIsTabs">
          <span class="ml-1">{{ getTitle }}span>
        div>
        <span :class="`${prefixCls}__extra-quick`" v-else @click="handleContext">
          <Icon icon="ion:chevron-down" />
        span>
      Dropdown>
    template>
    <script lang="ts">
    import { Dropdown } from '/@/components/Dropdown/index'
    import { useTabDropdown } from '../useTabDropdown'
    
    export default defineComponent({
      components: { Dropdown },
      setup(props) {
        const getIsTabs = computed(() => !props.isExtra)
    
        const getTrigger = computed((): ('contextmenu' | 'click' | 'hover') => 
          unref(getIsTabs) ? ['contextmenu'] : ['click']
        )
    
        const { getDropMenuList, handleMenuEvent, handleContextMenu } = useTabDropdown(props, getIsTabs)
    
        function handleContext(e) {
          props.tabItem && handleContextMenu(props.tabItem)(e)
        }
        return { getIsTabs, getTrigger, getDropMenuList, handleMenuEvent }
      }
    })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    【快应用】网络图片保存到相册失败案例
    WebRTC系列 -- iOS 音频采集之setParameter参数处理流程
    idea正常,jar启动报错
    FineBI 新增字段后 更新缓慢问题
    运维排查 | Systemd 之服务停止后状态为 failed
    Java解析生成二维码
    人工神经网络的基本模型,人工神经网络数学模型
    21天学习第十二天-Map集合
    s27.linux运维面试题分享
    ubuntu 校验 .desktop文件
  • 原文地址:https://blog.csdn.net/qq_36437172/article/details/127908140