Article archive: https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb
[Custom Vue Component] DropDown Menu (1.0) DropDownMenu: https://www.yuque.com/u27599042/coding_star/llltv52tchmatwg4
Component effect example
Constants that components depend on
In the src directory, create the constant directory, create a new tail_drop_down_constant.js file in it, and declare the constants that the component depends on.
/** * Constants related to the small tail drop-down menu component * @type {*} Constants related to the small tail drop-down menu component */ /** * The vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component * @type {string} The vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component */ // align left export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT = 'left' // Center it export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_CENTER = 'center' // right align export const DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_RIGHT = 'right' /** * The style class name corresponding to the vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component * @type {string} The style class name corresponding to the vertical alignment between the drop-down menu and the drop-down link of the small tail drop-down menu component */ // align left export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_LEFT = 'tail-drop-down-menu-box-v-align-left' // Center it export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_CENTER = 'tail-drop-down-menu-box-v-align-center' // right align export const DROP_DOWN_MENU_VERTICAL_ALIGN_CLASS_RIGHT = 'tail-drop-down-menu-box-v-align-right' // An array composed of style class names corresponding to the vertical alignment between all drop-down menus and drop-down links 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 variables that the component depends on
In the src directory, create the styles directory, create the tailComponentsThemeStyles directory in it, create new light.css and dark.css files in the tailComponentsThemeStyles directory, and declare the CSS variables related to theme styles that the components depend on.
/* * Bright theme style CSS variables related to the tail component */ :root[class*='light'] {<!-- --> /* * Small tail drop-down menu component style variable */ /* Background color of small tail drop-down menu component */ --tail-drop-down-bgc: #efefef00; /* Background color of menu item of small tail drop-down menu component */ --tail-drop-down-menu-item-bgc: #efefef99; /* Font color of small tail drop-down menu component */ --tail-drop-down-font-color: #333333; /* Mouse hover background color of small tail drop-down menu component */ --tail-drop-down-hover-bgc: #ccf4ed; /* Small tail drop-down menu component mouse hover font color */ --tail-drop-down-hover-font-color: #1b88e3; }
/* * Dark theme style CSS variables related to the tail component */ :root[class*='dark'] {<!-- --> /* * Small tail drop-down menu component style variable */ /* Background color of small tail drop-down menu component */ --tail-drop-down-bgc: #454545; /* Background color of menu item of small tail drop-down menu component */ --tail-drop-down-menu-item-bgc: #454545; /* Font color of small tail drop-down menu component */ --tail-drop-down-font-color: #efefef; /* Mouse hover background color of small tail drop-down menu component */ --tail-drop-down-hover-bgc: #565555; /* Small tail drop-down menu component mouse hover font color */ --tail-drop-down-hover-font-color: #00C9A7; }
Add light or dark class name on html element in index.html file
<html lang="zh-CN" class="light">
Introduce the CSS variables related to theme styles that the component depends on in the main.js file
Configure the src directory alias in the vue project: https://www.yuque.com/u27599042/coding_star/ogu2bhefy1fvahfv
import '@/styles/tailComponentsThemeStyles/light.css' import '@/styles/tailComponentsThemeStyles/dark.css'
Configure sass preprocessing
https://www.yuque.com/u27599042/coding_star/ua8sgyngldtaa2re
Component source code
In the src/components directory, create the TailDropDown.vue file and write the component in it
<!-- TailDropDown small tail drop-down menu component --> <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"; /** * Receive parameters passed by the parent component * @type {Prettify<Readonly<ExtractPropTypes<{}>>>>} */ const props = defineProps({<!-- --> // Whether the small tail drop-down menu component is shrunk and displayed. The shrunken display only displays the drop-down text link icon. isShrinkDisplay: {<!-- -->type: Boolean, default: false}, // Small tail drop-down menu component drop-down text link textLink: {<!-- -->type: String, default: 'Small tail drop-down menu drop-down text link'}, // Small tail drop-down menu component drop-down text link click event handler function textLinkClickHandler: {<!-- --> type: Function, default: () => {<!-- --> } }, // Small tail drop-down menu component drop-down text link height textLinkHeight: {<!-- -->type: String, default: '2rem'}, // Whether to enable drop-down image links to replace drop-down text links enableImageLink: {<!-- -->type: Boolean, default: false}, // Small tail drop-down menu component drop-down image link image address imageLinkUrl: {<!-- -->type: String, default: ''}, // Small tail drop-down menu component drop-down image link image size, the image defaults to a circle centered imageSize: {<!-- -->type: String, default: '2rem'}, // Small tail drop-down menu component drop-down image link click event handler function imageLinkClickHandler: {<!-- --> type: Function, default: () => {<!-- --> } }, //The distance between the drop-down menu of the small tail drop-down menu component and the drop-down link menuDistanceWithLink: {<!-- -->type: String, default: '0.5rem'}, // The vertical alignment between the drop-down menu of the small tail drop-down menu component and the drop-down link, which is left aligned by default menuVerticalAlign: {<!-- -->type: String, default: DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT}, // Small tail drop-down menu component drop-down menu item, an array composed of {menuItemText: '', menuItemClickHandler: ()=>{}} menuItems: {<!-- -->type: Array, default: []}, //The height of the drop-down menu item of the small tail drop-down menu component menuItemHeight: {<!-- -->type: String, default: '2rem'}, }) /** * Small tail drop-down menu component drop-down text link style * @type {<!-- -->{height: *}} */ const textLinkStyle = {<!-- --> height: props?.textLinkHeight } /** * Small tail drop-down menu component drop-down image link style * @type {<!-- -->{width: *, height: *}} */ const imageLinkStyle = {<!-- --> height: props?.imageSize, width: props?.imageSize, } /** * Small tail drop-down menu component drop-down menu item style * @type {<!-- -->{height: *}} */ const menuItemStyle = {<!-- --> height: props?.menuItemHeight } /** * Control whether the drop-down menu is displayed * @type {Ref<UnwrapRef<boolean>>} */ const dropDownMenuIsShow = ref(false) /** * Small tail drop-down menu component drop-down menu style * @type {<!-- -->{paddingTop: {default: string, type: String | StringConstructor}}} */ const menuStyle = {<!-- --> paddingTop: props?.menuDistanceWithLink } /** * Dynamically control the vertical alignment between drop-down menus and drop-down links */ //The class name of the drop-down menu const dropDownMenuClassName = computed(() => {<!-- --> // Determine the vertical alignment between the specified drop-down menu and the drop-down link 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> <!-- Small tail drop-down menu component --> <div class="tail-drop-down"> <!-- Small tail drop-down menu component drop-down link --> <div class="tail-drop-down-link" @mouseover="dropDownMenuIsShow = true" @mouseout="dropDownMenuIsShow = false" > <!-- Small tail drop-down menu component drop-down text link --> <div class="tail-drop-down-text-link" v-if="!enableImageLink" :style="textLinkStyle" @click="textLinkClickHandler" > <!-- Small tail drop-down menu component drop-down text link icon --> <span class="tail-drop-down-text-link-icon"> <slot name="dropDownTextLinkIcon"></slot> </span> <span v-show="!isShrinkDisplay">{<!-- -->{ textLink }}</span> <!-- Small tail drop-down menu component drop-down link icon When the mouse is hovering over the drop-down menu, the "small tail drop-down menu component drop-down link icon rotation style" is dynamically added when the drop-down menu is displayed. --> <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> <!-- Small tail drop-down menu component drop-down image link --> <slot name="dropDownImageLink" v-if="enableImageLink"> <div class="tail-drop-down-image-link" :style="imageLinkStyle" v-if="enableImageLink" > <img :src="imageLinkUrl" alt="Small tail drop-down menu drop-down image link"> </div> </slot> <!-- Small tail drop-down menu component drop-down menu box --> <div class="tail-drop-down-menu-box" :class="dropDownMenuClassName" :style="menuStyle" > <div class="tail-drop-down-menu" v-show="dropDownMenuIsShow" > <slot name="dropDownMenu"> <ul> <!-- Small tail drop-down menu component drop-down menu item --> <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"> /* * Small tail drop-down menu component */ .tail-drop-down {<!-- --> color: var(--tail-drop-down-font-color); /* * Clear default style */ div, ul, li, span {<!-- --> margin: 0; padding: 0; list-style: none; } /* * Small tail drop-down menu component drop-down link */ .tail-drop-down-link {<!-- --> position: relative; display: inline-block; cursor: pointer; // Text cannot be selected user-select: none; /* * Small tail drop-down menu component drop-down text link */ .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; //The text does not wrap white-space: nowrap; & amp;:hover {<!-- --> background-color: var(--tail-drop-down-hover-bgc); color: var(--tail-drop-down-hover-font-color); } /* * Small tail drop-down menu component drop-down link icon */ .tail-drop-down-link-icon {<!-- --> width: 100%; height: 100%; margin-left: 0.5rem; transition: all 0.3s; //Set the rotation center point x y transform-origin: 50% 50%; display: flex; justify-content: center; align-items: end; } /* * Small tail drop-down menu component drop-down link icon rotation style */ .tail-drop-down-link-icon-rotate {<!-- --> transform: rotateZ(180deg); transition-delay: -0.1s; } } /* * Small tail drop-down menu component drop-down picture link */ .tail-drop-down-image-link {<!-- --> border-radius: 50%; background-color: var(--tail-drop-down-bgc); transition: all 0.5s; overflow: hidden; & amp;:hover {<!-- --> transform: rotateZ(360deg); } img {<!-- --> width: 100%; } } /* * Small tail drop-down menu component drop-down menu box */ .tail-drop-down-menu-box {<!-- --> position: absolute; top: 100%; /* * Small tail drop-down menu component drop-down menu */ .tail-drop-down-menu {<!-- --> border-radius: 0.5rem; // If overflow hiding will affect the display of the submenu // overflow: hidden; /* * Small tail drop-down menu component drop-down menu item */ .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; //The text does not wrap white-space: nowrap; & amp;:hover {<!-- --> background-color: var(--tail-drop-down-hover-bgc); color: var(--tail-drop-down-hover-font-color); } //The first child element of the current element's parent element & amp;:first-child {<!-- --> border-top-right-radius: 0.5rem; border-top-left-radius: 0.5rem; } //The last child element of the current element's parent element & amp;:last-child {<!-- --> border-bottom-right-radius: 0.5rem; border-bottom-left-radius: 0.5rem; } } } } /* * The vertical alignment between the drop-down menu box and the drop-down link of the small tail drop-down menu component */ // align left .tail-drop-down-menu-box-v-align-left {<!-- --> left: 0; } // center alignment .tail-drop-down-menu-box-v-align-center {<!-- --> left: 50%; transform: translateX(-50%); } // right align .tail-drop-down-menu-box-v-align-right {<!-- --> right: 0; } } } </style>
Component usage instructions
props component properties
Attributes | Attribute description | Attribute value type | Attribute default value |
---|---|---|---|
isShrinkDisplay | Whether the small tail drop-down menu component is shrunk and displayed. The shrunk display only displays the drop-down link text icon | Boolean | false |
textLink | Small tail drop-down menu component drop-down link text | String | ‘ Small tail drop-down menu drop-down text link’ |
textLinkClickHandler | Small tail drop-down menu component drop-down link text click event handler function | Function | () => {} |
textLinkHeight | Small tail drop-down menu component drop-down link text Height | String | ‘2rem’ |
enableImageLink | Whether to enable the drop-down link image to replace the drop-down link text | Boolean | false |
imageLinkUrl | Small tail drop-down menu component drop-down link image image address | String | ” |
imageSize | Small tail drop-down menu component drop-down link image image size, image default Circle Centered | String | ‘2rem’ |
imageLinkClickHandler | Small tail drop-down menu component drop-down link Image click event handling function | Function | () => {} |
menuDistanceWithLink | The distance between the drop-down menu and the drop-down link of the small tail drop-down menu component | String | ‘0.5rem’ |
menuVerticalAlign | The vertical alignment between the small tail drop-down menu component drop-down menu and the drop-down link, the default left alignment | String | DROP_DOWN_MENU_VERTICAL_ALIGN_WAY_LEFT |
Value reference: https://www.yuque.com/u27599042/coding_star/kcoem6dgyn8drglb#CYUne | |||
menuItems | The small tail drop-down menu component drop-down menu item consists of {menuItemText: '', menuItemClickHandler: () =>{}} Array |
Array | [] |
menuItemHeight | Small tail drop-down menu component drop-down menu item height | String | ‘2rem’ |
slot slot
Slot Name | Slot Description |
---|---|
dropDownTextLinkIcon | The icon before the drop-down link text of the small tail drop-down menu component |
dropDownLinkIcon | The drop-down link icon of the small tail drop-down menu component (after the drop-down link text icon) |
dropDownImageLink | Small tail drop-down menu component drop-down link image, you need to make the enableImageLink component property true (use this slot element to replace the drop-down link text) |
dropDownMenu | Drop-down menu, this slot will replace the default drop-down menu item |