文章归档:https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb
[自定义 Vue 组件] 下拉菜单(1.0) DropDownMenu:https://www.yuque.com/u27599042/coding_star/llltv52tchmatwg4
组件效果示例
组件所依赖的常量
在 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 文件,在其中编写组件
<!--
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 | 下拉菜单,该插槽会替换默认的下拉菜单项 |