[自定义 Vue 组件] 小尾巴下拉菜单组件(2.0) TailDropDown

这篇具有很好参考价值的文章主要介绍了[自定义 Vue 组件] 小尾巴下拉菜单组件(2.0) TailDropDown。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章归档:https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb

[自定义 Vue 组件] 下拉菜单(1.0) DropDownMenu:https://www.yuque.com/u27599042/coding_star/llltv52tchmatwg4

组件效果示例

[自定义 Vue 组件] 小尾巴下拉菜单组件(2.0) TailDropDown,小尾巴的编程知识星球,vue.js,javascript,前端,前端框架,vue,组件,web

组件所依赖的常量

在 src 目录下,创建 constant 目录,在其中新建 tail_drop_down_constant.js 文件,在其中声明组件所依赖的常量

/**
 * 与小尾巴下拉菜单组件相关的常量
 * @type {*} 与小尾巴下拉菜单组件相关的常量
 */

/**
 * 小尾巴下拉菜单组件下拉菜单与下拉链接之间的垂直对其方式
 * @type {string} 小尾巴下拉菜单组件下拉菜单与下拉链接之间的垂直对其方式
 */
// 左对齐
export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT = 'left'
// 居中对其
export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER = 'center'
// 右对齐
export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT = 'right'

/**
 * 小尾巴下拉菜单组件下拉菜单与下拉链接之间的垂直对其方式所对应的样式类名
 * @type {string} 小尾巴下拉菜单组件下拉菜单与下拉链接之间的垂直对其方式所对应的样式类名
 */
// 左对齐
export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT = 'tail-drop-down-menu-box-v-align-left'
// 居中对其
export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER = 'tail-drop-down-menu-box-v-align-center'
// 右对齐
export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT = 'tail-drop-down-menu-box-v-align-right'
// 所有下拉菜单与下拉链接之间的垂直对其方式所对应的样式类名组成的数组
export const dropDownMenuVerticalAlignClasses = [
    DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT,
    DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER,
    DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT
]

组件所依赖的 CSS 变量

在 src 目录下,创建 styles 目录,在其中创建 tailComponentsThemeStyles 目录,在 tailComponentsThemeStyles 目录中新建 light.css 与 dark.css 文件,在其中声明组件所依赖的和主题样式相关的 CSS 变量

/*
 * 和小尾巴组件相关的亮色主题样式 CSS 变量
 */
:root[class*='light'] {
    /*
     * 小尾巴下拉菜单组件样式变量
     */
    /* 小尾巴下拉菜单组件背景颜色 */
    --tail-drop-down-bgc: #efefef00;
    /* 小尾巴下拉菜单组件菜单项背景颜色 */
    --tail-drop-down-menu-item-bgc: #efefef99;
    /* 小尾巴下拉菜单组件字体颜色 */
    --tail-drop-down-font-color: #333333;
    /* 小尾巴下拉菜单组件鼠标悬浮背景颜色 */
    --tail-drop-down-hover-bgc: #ccf4ed;
    /* 小尾巴下拉菜单组件鼠标悬浮字体颜色 */
    --tail-drop-down-hover-font-color: #1b88e3;
}
/*
 * 和小尾巴组件相关的暗色主题样式 CSS 变量
 */
:root[class*='dark'] {
    /*
     * 小尾巴下拉菜单组件样式变量
     */
    /* 小尾巴下拉菜单组件背景颜色 */
    --tail-drop-down-bgc: #454545;
    /* 小尾巴下拉菜单组件菜单项背景颜色 */
    --tail-drop-down-menu-item-bgc: #454545;
    /* 小尾巴下拉菜单组件字体颜色 */
    --tail-drop-down-font-color: #efefef;
    /* 小尾巴下拉菜单组件鼠标悬浮背景颜色 */
    --tail-drop-down-hover-bgc: #565555;
    /* 小尾巴下拉菜单组件鼠标悬浮字体颜色 */
    --tail-drop-down-hover-font-color: #00C9A7;
}

在 index.html 文件中的 html 元素上添加 light 或 dark 类名

<html lang="zh-CN" class="light">

在 main.js 文件中引入组件所依赖的和主题样式相关的 CSS 变量

vue 项目中配置 src 目录别名:https://www.yuque.com/u27599042/coding_star/ogu2bhefy1fvahfv

import '@/styles/tailComponentsThemeStyles/light.css'
import '@/styles/tailComponentsThemeStyles/dark.css'

配置 sass 预处理

https://www.yuque.com/u27599042/coding_star/ua8sgyngldtaa2re

组件源码

在 src/components 目录下,创建 TailDropDown.vue 文件,在其中编写组件文章来源地址https://www.toymoban.com/news/detail-743001.html

<!--
TailDropDown 小尾巴下拉菜单组件
-->
<script setup>
import {ref, computed} from 'vue'
import {
  DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER,
  DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT,
  DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT,
  DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER,
  DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT,
  DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT
} from "@/constant/tail_drop_down_constant.js";

/**
 * 接收父组件传递的参数
 * @type {Prettify<Readonly<ExtractPropTypes<{}>>>}
 */
const props = defineProps({
  // 小尾巴下拉菜单组件是否收缩显示,收缩显示只显示下拉文本链接图标
  isShrinkDisplay: {type: Boolean, default: false},
  // 小尾巴下拉菜单组件下拉文本链接
  textLink: {type: String, default: '小尾巴下拉菜单下拉文本链接'},
  // 小尾巴下拉菜单组件下拉文本链接点击事件处理函数
  textLinkClickHandler: {
    type: Function, default: () => {
    }
  },
  // 小尾巴下拉菜单组件下拉文本链接高度
  textLinkHeight: {type: String, default: '2rem'},
  // 是否启用下拉图片链接替换下拉文本链接
  enableImageLink: {type: Boolean, default: false},
  // 小尾巴下拉菜单组件下拉图片链接图片地址
  imageLinkUrl: {type: String, default: ''},
  // 小尾巴下拉菜单组件下拉图片链接图片大小,图片默认圆形居中
  imageSize: {type: String, default: '2rem'},
  // 小尾巴下拉菜单组件下拉图片链接点击事件处理函数
  imageLinkClickHandler: {
    type: Function, default: () => {
    }
  },
  // 小尾巴下拉菜单组件下拉菜单与下拉链接之间的距离
  menuDistanceWithLink: {type: String, default: '0.5rem'},
  // 小尾巴下拉菜单组件下拉菜单与下拉链接之间的垂直对其方式,默认左对齐
  menuVerticalAlign: {type: String, default: DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT},
  // 小尾巴下拉菜单组件下拉菜单项,由 {menuItemText: '', menuItemClickHandler: ()=>{}} 组成的数组
  menuItems: {type: Array, default: []},
  // 小尾巴下拉菜单组件下拉菜单项高度
  menuItemHeight: {type: String, default: '2rem'},
})

/**
 * 小尾巴下拉菜单组件下拉文本链接样式
 * @type {{height: *}}
 */
const textLinkStyle = {
  height: props?.textLinkHeight
}

/**
 * 小尾巴下拉菜单组件下拉图片链接样式
 * @type {{width: *, height: *}}
 */
const imageLinkStyle = {
  height: props?.imageSize,
  width: props?.imageSize,
}

/**
 * 小尾巴下拉菜单组件下拉菜单项样式
 * @type {{height: *}}
 */
const menuItemStyle = {
  height: props?.menuItemHeight
}

/**
 * 控制下拉菜单是否显示
 * @type {Ref<UnwrapRef<boolean>>}
 */
const dropDownMenuIsShow = ref(false)

/**
 * 小尾巴下拉菜单组件下拉菜单样式
 * @type {{paddingTop: {default: string, type: String | StringConstructor}}}
 */
const menuStyle = {
  paddingTop: props?.menuDistanceWithLink
}

/**
 * 动态控制下拉菜单与下拉链接之间的垂直对其方式
 */
// 下拉菜单的 class 类名
const dropDownMenuClassName = computed(() => {
  // 判断指定的下拉菜单与下拉链接之间的垂直对其方式
  switch (props?.menuVerticalAlign) {
    case DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT:
      return DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT
    case DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER:
      return DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER
    case DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT:
      return DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT
  }
})

</script>

<template>
  <!-- 小尾巴下拉菜单组件 -->
  <div class="tail-drop-down">
    <!-- 小尾巴下拉菜单组件下拉链接 -->
    <div
        class="tail-drop-down-link"
        @mouseover="dropDownMenuIsShow = true"
        @mouseout="dropDownMenuIsShow = false"
    >
      <!-- 小尾巴下拉菜单组件下拉文本链接 -->
      <div
          class="tail-drop-down-text-link"
          v-if="!enableImageLink"
          :style="textLinkStyle"
          @click="textLinkClickHandler"
      >
        <!-- 小尾巴下拉菜单组件下拉文本链接图标 -->
        <span class="tail-drop-down-text-link-icon">
          <slot name="dropDownTextLinkIcon"></slot>
        </span>
        <span v-show="!isShrinkDisplay">{{ textLink }}</span>
        <!--
          小尾巴下拉菜单组件下拉链接图标
          鼠标悬浮于下拉菜单,下拉菜单显示时动态添加“小尾巴下拉菜单组件下拉链接图标旋转样式”
        -->
        <div
            v-show="menuItems.length > 0"
            class="tail-drop-down-link-icon"
            :class="dropDownMenuIsShow ? 'tail-drop-down-link-icon-rotate' : ''"
        >
          <slot name="dropDownLinkIcon"></slot>
        </div>
      </div>
      <!-- 小尾巴下拉菜单组件下拉图片链接 -->
      <slot name="dropDownImageLink" v-if="enableImageLink">
        <div
            class="tail-drop-down-image-link"
            :style="imageLinkStyle"
            v-if="enableImageLink"
        >
          <img :src="imageLinkUrl" alt="小尾巴下拉菜单下拉图片链接">
        </div>
      </slot>
      <!-- 小尾巴下拉菜单组件下拉菜单盒子 -->
      <div
          class="tail-drop-down-menu-box"
          :class="dropDownMenuClassName"
          :style="menuStyle"
      >
        <div
            class="tail-drop-down-menu"
            v-show="dropDownMenuIsShow"
        >
          <slot name="dropDownMenu">
            <ul>
              <!-- 小尾巴下拉菜单组件下拉菜单项 -->
              <li
                  class="tail-drop-down-menu-item"
                  v-for="(menuItem, idx) in menuItems"
                  :key="idx"
                  :style="menuItemStyle"
                  @click="menuItem?.menuItemClickHandler"
              >
                <span>{{ menuItem?.menuItemText }}</span>
              </li>
            </ul>
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
/*
 * 小尾巴下拉菜单组件
 */
.tail-drop-down {
  color: var(--tail-drop-down-font-color);

  /*
   * 清除默认样式
   */
  div, ul, li, span {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  /*
   * 小尾巴下拉菜单组件下拉链接
   */
  .tail-drop-down-link {
    position: relative;
    display: inline-block;
    cursor: pointer;
    // 文字不能被选中
    user-select: none;

    /*
     * 小尾巴下拉菜单组件下拉文本链接
     */
    .tail-drop-down-text-link {
      box-sizing: border-box;
      padding: 0.5rem;
      border-radius: 0.5rem;
      background-color: var(--tail-drop-down-bgc);
      transition: all 0.3s;
      display: flex;
      justify-content: center;
      align-items: center;
      // 文本不换行
      white-space: nowrap;

      &:hover {
        background-color: var(--tail-drop-down-hover-bgc);
        color: var(--tail-drop-down-hover-font-color);
      }

      /*
       * 小尾巴下拉菜单组件下拉链接图标
       */
      .tail-drop-down-link-icon {
        width: 100%;
        height: 100%;
        margin-left: 0.5rem;
        transition: all 0.3s;
        // 设置旋转中心点 x y
        transform-origin: 50% 50%;
        display: flex;
        justify-content: center;
        align-items: end;
      }

      /*
       * 小尾巴下拉菜单组件下拉链接图标旋转样式
       */
      .tail-drop-down-link-icon-rotate {
        transform: rotateZ(180deg);
        transition-delay: -0.1s;
      }
    }

    /*
     * 小尾巴下拉菜单组件下拉图片链接
     */
    .tail-drop-down-image-link {
      border-radius: 50%;
      background-color: var(--tail-drop-down-bgc);
      transition: all 0.5s;
      overflow: hidden;

      &:hover {
        transform: rotateZ(360deg);
      }

      img {
        width: 100%;
      }
    }

    /*
     * 小尾巴下拉菜单组件下拉菜单盒子
     */
    .tail-drop-down-menu-box {
      position: absolute;
      top: 100%;

      /*
       * 小尾巴下拉菜单组件下拉菜单
       */
      .tail-drop-down-menu {
        border-radius: 0.5rem;
        // 如果溢出隐藏会影响子菜单的显示
        // overflow: hidden;

        /*
         * 小尾巴下拉菜单组件下拉菜单项
         */
        .tail-drop-down-menu-item {
          z-index: 1;
          box-sizing: border-box;
          padding: 0.5rem;
          background-color: var(--tail-drop-down-menu-item-bgc);
          transition: all 0.3s;
          overflow: hidden;
          display: flex;
          justify-content: start;
          align-items: center;
          // 文本不换行
          white-space: nowrap;

          &:hover {
            background-color: var(--tail-drop-down-hover-bgc);
            color: var(--tail-drop-down-hover-font-color);
          }

          // 当前元素的父元素的第一个子元素
          &:first-child {
            border-top-right-radius: 0.5rem;
            border-top-left-radius: 0.5rem;
          }

          // 当前元素的父元素的最后一个子元素
          &:last-child {
            border-bottom-right-radius: 0.5rem;
            border-bottom-left-radius: 0.5rem;
          }
        }
      }
    }

    /*
     * 小尾巴下拉菜单组件下拉菜单盒子与下拉链接之间的垂直对其方式
     */
    // 左对齐
    .tail-drop-down-menu-box-v-align-left {
      left: 0;
    }

    // 居中对齐
    .tail-drop-down-menu-box-v-align-center {
      left: 50%;
      transform: translateX(-50%);
    }

    // 右对齐
    .tail-drop-down-menu-box-v-align-right {
      right: 0;
    }
  }
}
</style>

组件使用说明

props 组件属性

属性 属性说明 属性值类型 属性默认值
isShrinkDisplay 小尾巴下拉菜单组件是否收缩显示,收缩显示只显示下拉链接文本图标 Boolean false
textLink 小尾巴下拉菜单组件下拉链接文本 String ‘小尾巴下拉菜单下拉文本链接’
textLinkClickHandler 小尾巴下拉菜单组件下拉链接文本点击事件处理函数 Function () => {}
textLinkHeight 小尾巴下拉菜单组件下拉链接文本高度 String ‘2rem’
enableImageLink 是否启用下拉链接图片替换下拉链接文本 Boolean false
imageLinkUrl 小尾巴下拉菜单组件下拉链接图片图片地址 String ‘’
imageSize 小尾巴下拉菜单组件下拉链接图片图片大小,图片默认圆形居中 String ‘2rem’
imageLinkClickHandler 小尾巴下拉菜单组件下拉链接图片点击事件处理函数 Function () => {}
menuDistanceWithLink 小尾巴下拉菜单组件下拉菜单与下拉链接之间的距离 String ‘0.5rem’
menuVerticalAlign 小尾巴下拉菜单组件下拉菜单与下拉链接之间的垂直对其方式,默认左对齐 String DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT
取值参考:https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb#CYUne
menuItems 小尾巴下拉菜单组件下拉菜单项,由 {menuItemText: '', menuItemClickHandler: ()=>{}} 组成的数组 Array []
menuItemHeight 小尾巴下拉菜单组件下拉菜单项高度 String ‘2rem’

slot 插槽

插槽名称 插槽说明
dropDownTextLinkIcon 小尾巴下拉菜单组件下拉链接文本前的图标
dropDownLinkIcon 小尾巴下拉菜单组件下拉链接图标(下拉链接文本后的图标)
dropDownImageLink 小尾巴下拉菜单组件下拉链接图片,需要使 enableImageLink 组件属性为 true (使用此插槽元素替换下拉链接文本)
dropDownMenu 下拉菜单,该插槽会替换默认的下拉菜单项

到了这里,关于[自定义 Vue 组件] 小尾巴下拉菜单组件(2.0) TailDropDown的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包