flex menu study

本文介绍如何在AS3中实现菜单的缓动效果,通过使用缓动算法为菜单项添加平滑过渡动画,增强用户体验。
[url]http://www.flexrain.cn/flex/as3-menueasing.html[/url]
<template> <header class="header"> <div class="header-left" @click="navigateToHome"> <h1>在线考试系统</h1> </div> <div class="header-center"> <el-menu mode="horizontal" :default-active="activeIndex" @select="handleMenuSelect" background-color="#4b0082" text-color="white" active-text-color="#ffd700" > <el-menu-item v-for="menu in menuItems" :key="menu.index" :index="menu.index" > {{ menu.label }} </el-menu-item> </el-menu> </div> <div class="header-right"> <!-- <div class="header-container">--> <div class="current-time"> {{ formattedDate }} <span class="time-separator">|</span> {{ formattedTime }} </div> <!-- </div>--> <!-- 用户下拉菜单 --> <el-dropdown @command="handleUserCommand"> <div class="user-info" @click.stop> <el-avatar size="small" :src="userAvatar" alt="用户头像" /> <span class="username">{{ userStore.user.user?.username || '未登录' }}</span> <el-icon class="icon-arrow"> <ArrowDown /> </el-icon> </div> <template #dropdown> <el-dropdown-menu> <el-dropdown-item v-for="item in userActions" :key="item.command" :command="item.command" :type="item.type" > {{ item.label }} </el-dropdown-item> <el-divider class="dropdown-divider" v-if="showDivider"/> <el-dropdown-item command="logout" type="danger" > 退出登录 </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </div> </header> </template> <script setup lang="ts"> import { ref, onMounted, onUnmounted, computed } from 'vue' import { ArrowDown } from '@element-plus/icons-vue' import { ElMessage,ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'; // 导入图片时使用Vite的新特性,确保类型安全 import { useRouter} from 'vue-router'; import { useUserStore } from '@/stores/userStore' import { useProfileStore } from '@/stores/profile' const router = useRouter(); const userStore = useUserStore(); const profileStore = useProfileStore(); console.log('username', userStore.user.user?.username); // 定义菜单项接口,确保类型安全 interface MenuItem { index: string label: string route?: string } // 定义用户操作接口 interface UserAction { command: string label: string type?: 'primary' | 'success' | 'warning' | 'danger' | 'info' } // 定义用户信息接口 interface UserInfo { name: string role: string avatar: string } // 导航菜单数据 const menuItems: MenuItem[] = [ { index: '1', label: '首页', route: '/home' }, { index: '2', label: '学习', route: '/study' }, { index: '3', label: '练习', route: '/practice' }, { index: '4', label: '考试中心', route: '/examinationCenter' }, { index: '5', label: '成绩查询', route: '/scoreInquiry' } ] // 用户操作下拉菜单数据 const userActions: UserAction[] = [ { command: 'profile', label: '个人资料', route: '/userCenter' }, { command: 'settings', label: '系统设置', route: '/' }, { command: 'help', label: '帮助中心' , route: '/'} ] // 是否显示分割线 const showDivider = ref(true) // 存储当前时间的响应式变量 const currentTime = ref(new Date()); // 当前激活的菜单索引 const activeIndex = ref<string>(menuItems[0].index) // 导航方法 - 新增返回首页方法 const navigateToHome = () => { router.push('/home') } // 计算属性获取用户头像,优先使用profileStore中的头像,其次使用userStore,最后使用默认头像 const userAvatar = computed(() => { // 从profileStore获取(如果有个人中心设置的头像) if (profileStore.profile?.avatar) { return profileStore.profile.avatar; } // 从userStore获取(登录返回的头像) if (userStore.user?.user?.avatar) { return userStore.user.user.avatar; } // 默认头像 return new URL('@/assets/images/avatar.png', import.meta.url).href; }); // 格式化日期为 "YYYY年MM月DD日 星期X" const formattedDate = computed(() => { const date = currentTime.value; const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const weekdays = ['日', '一', '二', '三', '四', '五', '六']; const weekday = weekdays[date.getDay()]; return `${year}年${month}月${day}日 星期${weekday}`; }); // 格式化时间为 "HH:MM:SS" const formattedTime = computed(() => { const date = currentTime.value; const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; }); // 处理菜单选择事件 const handleMenuSelect = (index: string) => { activeIndex.value = index const selectedMenu = menuItems.find(item => item.index === index) if (selectedMenu?.route) { // 实际项目中使用路由跳转 router.push(selectedMenu.route) // ElMessage.info(`导航至 ${selectedMenu.label}`) } } // 处理用户下拉菜单命令 const handleUserCommand = (command: string) => { switch(command) { case 'profile': ElMessage.info('查看个人资料') router.push('/userCenter') break case 'settings': ElMessage.info('打开系统设置') router.push('/settings') break case 'help': ElMessage.info('查看帮助中心') router.push('/help') break case 'logout': handleLogout() break default: ElMessage.warning(`未处理的命令: ${command}`) } } // 退出登录处理函数 const handleLogout = () => { // 实际项目中应使用ElMessageBox确认 // 基础用法 ElMessageBox.alert('确定要退出登录吗?', '系统提示', { confirmButtonText: '确定', // 按钮文本 callback: action => { // 点击按钮后的回调,action 为 'confirm' // console.log('点击了确定'); ElMessage.success('已成功退出登录') // 清除登录状态并跳转 localStorage.removeItem('token'); router.push('/login') } }); } // 定时器ID,用于组件销毁时清除 let timer = null; // 组件挂载时启动定时器,每秒更新时间 onMounted(() => { profileStore.initProfile(); // 立即更新一次时间 currentTime.value = new Date(); // 每秒更新一次 timer = setInterval(() => { currentTime.value = new Date(); }, 1000); }); // 组件销毁时清除定时器,防止内存泄漏 onUnmounted(() => { if (timer) { clearInterval(timer); timer = null; } }); </script> <style scoped> .header { display: flex; align-items: center; height: 60px; background-color: #4b0082; color: white; padding: 0 20px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); } .header-left { width: 200px; } .header-left h1 { font-size: 1.4rem; margin: 0; font-weight: 600; } .header-center { flex: 1; } /* 右侧用户区域 */ .header-right { width: 500px; display: flex; align-items: center; justify-content: flex-end; gap: 15px; } /* 调整 el-divider 在下拉菜单中的样式 */ .dropdown-divider { margin: 4px 0; /* 减小上下间距,适应下拉菜单 */ padding: 0; /* 清除默认内边距 */ } /* 当前时间显示 */ .current-time { color: #ffffff; font-size: 1rem; display: flex; align-items: center; gap: 0.5rem; line-height: 60px; } .time-separator { color: #999999; } /* 当前时间显示 end */ /* 用户信息区域 */ .user-info { display: flex; align-items: center; gap: 8px; color: white; cursor: pointer; padding: 4px 10px; border-radius: 20px; transition: background-color 0.2s; } .user-info:hover { background-color: rgba(255, 255, 255, 0.1); } .user-avatar { border: 2px solid rgba(255, 255, 255, 0.2); } .username { font-size: 0.9rem; font-weight: 500; } .icon-arrow { font-size: 14px; transition: transform 0.2s; } .icon-arrow { font-size: 14px; transition: transform 0.2s; } /* 移除菜单底部边框,使其与头部融合 */ :deep(.el-menu--horizontal) { border-bottom: none; height: 100%; /* 让菜单高度与头部一致 */ } /* 调整菜单项样式,使其充满头部高度 */ :deep(.el-menu--horizontal .el-menu-item) { height: 60px; line-height: 60px; padding: 0 20px; transition: all 0.2s; } /* 优化激活菜单项样式 */ :deep(.el-menu--horizontal .el-menu-item.is-active) { background-color: rgba(255, 255, 255, 0.15); color: #ffd700; } /* 优化菜单项悬停样式 */ :deep(.el-menu--horizontal .el-menu-item:hover) { background-color: rgba(255, 255, 255, 0.1); } /* 处理子菜单样式 */ :deep(.el-menu--horizontal .el-submenu .el-submenu__title) { height: 60px; line-height: 60px; padding: 0 20px; } :deep(.el-menu--horizontal .el-submenu:hover .el-submenu__title) { background-color: rgba(255, 255, 255, 0.1); } /* 移动端样式 */ .mobile-menu-btn { display: none; color: white; background-color: transparent; } .mobile-menu { position: absolute; top: 60px; left: 0; right: 0; z-index: 1000; display: none; } @media (max-width: 768px) { .header-center { display: none; } .mobile-menu-btn { display: block; } .mobile-menu { display: block; } .header-left h1 { font-size: 1.2rem; } .username { display: none; } .current-time { font-size: 0.875rem; } } </style> 修复点击两次才选中li标签才显示激活选中样式
10-27
<template> <header class="header" :class="[!expandHeader && 'hidden']"> <div class="box"> <!--wrapper flex justify-between--> <div class="left"> <h1 class="logo-wrap" :title="title"> <router-link to="/"> <img v-if="expandHeader" src="@/assets/logo.png" class="logo" :alt="title"/> <img v-else src="@/assets/logo-icon.png" class="logo" :alt="title"/> </router-link> </h1> <el-menu :default-active="routerPath" class="menu-wrap" :collapse="!expandHeader" @open="handleOpen" @close="handleClose" > <el-menu-item v-for="(item, index) in menuData" :index="item.path" :key="index" @click="goPage(item)"> <SvgIcon v-if="item.iconName" :name="item.iconName" size="16"/> <SvgRender v-if="item.icon" :url="item.icon" size="16"/> <!-- <img :src="getPreview(item.icon)" />--> <template #title>{{ item.name }}</template> </el-menu-item> </el-menu> <div class="recently-list" v-if="expandHeader && recentlyList.length"> <h3>使用记录</h3> <ul class="scrollbar"> <li v-for="(item, i) in recentlyList" :key="item.appId + i" @click="goDetail(item, '访问记录')"> <p :title="item.appName"> <el-image :src="getPreview(item.appIconUrl)" fit="cover" :size="24" lazy> <template #error><div class="image-slot"><img :src="defaultAvatarUrl" /></div></template> </el-image> <strong class="single-line">{{item.appName}}</strong> </p> <el-dropdown> <el-icon @click.stop=""><MoreFilled /></el-icon> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @mousedown.native="handleDelete(item)">删除</el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </li> </ul> </div> </div> <div class="right flex"> <el-dropdown v-if="userInfo.email"> <div class="avatar" :title="userInfo.email"> <el-image :src="avatarUrl"> <template #error><img :src="defaultAvatarUrl" /></template> </el-image> <p v-if="expandHeader">{{userInfo.userName}}</p> </div> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @mousedown.native="onLogout"> <el-icon class="arrow"><SwitchButton/></el-icon> 退出</el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> <el-button type="primary" class="add-btn" id="refTour3" @click="goPA"><el-icon color="#ffffff"><Plus/></el-icon><span v-if="expandHeader">创建应用</span></el-button> </div> </div> <div class="action-arrow" @click="handleExpandHeader"> <img src="@/assets/icons/nav-arrow-left.png"/> </div> </header> </template> <script> import {Search, Plus, CaretBottom, SwitchButton, MoreFilled} from '@element-plus/icons-vue' import SvgRender from '@/components/SvgRender' import {getUserInfo, sendData} from '@/utils/api' import {logoutSSO} from '@/utils/auth' import {goPA, isUrl} from '@/utils' import { mapState, mapActions } from 'pinia' import { useStore } from '@/stores' import ubs from '@/utils/ubs' import localStore from 'store' export default { name: 'AppHeader', components: {Search, Plus, CaretBottom, SwitchButton, MoreFilled, SvgRender}, data() { return { title:'AI应用集市', searchVal: '', menuActive: '1', menuData: [ {name: '首页', path: '/', iconName: 'nav-home'}, {name: '优秀案例', path: '/case', iconName: 'nav-case'}, {name: '创新大赛', path: '/contest', iconName: 'nav-contest'}, {name: '社区讨论', url: 'http://wk-bbs-web-test6-8080.msxf.msxfyun.test/', iconName: 'nav-bbs'}, {name: '学习资料', url: 'http://wk-bbs-web-test6-8080.msxf.msxfyun.test/', iconName: 'nav-study'}, ] } }, computed: { ...mapState(useStore, ['getPreview','userInfo', 'avatarUrl', 'defaultAvatarUrl', 'params', 'expandHeader', 'recentlyList']), showInput() { return this.params.searchKW || this.$route.path.includes('/search') }, showSearch() { return this.$route.name === 'home' }, routerPath() { console.log('routerPath---:',this.$route.path) return this.$route.path }, }, created() { let winWidth = document.documentElement.clientWidth if(!this.userInfo?.email) { getUserInfo((userInfo) => { if(winWidth < 1288) { // 小屏自动收起 let openTourData = localStore.get('openTourData') let email = userInfo.email console.log('email---:', email, openTourData) // 功能指引-已显示-自动收起 if(openTourData && openTourData[email]){ this.setExpandHeader(false) } } ubs.initUbs(userInfo, () => { console.log('ubs---初始完成') this.$bus.emit('initUBS') }) }) } this.getMenuData() this.getUserAvatarUrl() this.getRecentlyUsed() }, methods: { ...mapActions(useStore, ['getUserAvatarUrl', 'setExpandHeader','getPreview', 'getRecentlyUsed']), goPA(){ ubs.ubsData({module: '创建应用区域', $element_name: '创建应用'}) goPA() }, goPage(item) { // 处理外部链接 console.log('item----:', item, this.routerPath) const { url, isIframe } = item if (isUrl(item.path)) { return window.open(item.path) } item.path && this.$router.push(item.path) }, handleOpen(key, keyPath) { console.log(key, keyPath) }, handleClose() {}, getMenuData(item){ this.$request({url: `/frontend/appManage/listFrontMenu`, method: 'GET'}).then(res => { if(res.code === '1') { this.menuData = res.data } }) }, handleDelete(item){ this.$request({url: `/frontend/appManage/deleteRecentlyUsed/${item.appId}`, method: 'POST'}).then(res => { if(res.code === '1') { this.$message.success('删除成功!') this.getRecentlyUsed() } }) }, handleExpandHeader(){ this.setExpandHeader(!this.expandHeader) }, goDetail(item, module) { sendData('app_click', item.appId) ubs.ubsData({module, $element_name: item.appName}) if(location.pathname.includes('/application/')){ this.$router.replace({path: `/application/${item.appId}`}) } else { this.$router.push({path: `/application/${item.appId}`}) } }, onLogout() { logoutSSO() }, handleOver() { this.$nextTick(() => { this.$refs.searchInput && this.$refs.searchInput.focus() }) }, handleSearch() { this.$bus.emit('search', this.params.searchKW) this.$nextTick(() => { this.$refs.searchInput && this.$refs.searchInput.focus() }) } }, } </script> <style scoped lang="scss"> @use "@/styles/header"; </style> 这里menu点击菜单的一个外部链接,不需要此时菜单时激活状态,怎么修改
08-21
<template> <view class="demo-container"> <!-- 标题 --> <text class="title">📌 zy-popup-dropdown-menu 完整使用示例</text> <!-- 下拉菜单区域 --> <view class="section"> <text class="label">选择分类:</text> <zy-popup-dropdown-menu v-if="isComponentReady" v-model="selectedValue" :data="categoryList" label-key="label" value-key="value" :reference-ref="triggerRef" @change="handleChange" @open="onOpen" @close="onClose" > <!-- 自定义触发器 --> <template #reference="{ open, close, toggle }"> <view ref="triggerRef" class="dropdown-trigger" @tap="open"> <text class="trigger-text">{{ displayText }}</text> <text class="arrow">▼</text> </view> </template> </zy-popup-dropdown-menu> </view> <!-- 控制按钮 --> <view class="action-box"> <button @tap="callOpen">通过 ref 打开</button> <button @tap="callClose">通过 ref 关闭</button> <button @tap="resetSelection">重置选择</button> </view> <!-- 当前状态展示 --> <view class="result-box"> <text>当前选中值: {{ selectedValue || '无' }}</text> <text>当前标签: {{ displayText }}</text> </view> </view> </template> <script setup> import { ref, computed } from 'vue' const isComponentReady = ref(false) onMounted(() => { nextTick(() => { isComponentReady.value = true // 延迟挂载下拉菜单 console.log('组件已准备就绪') }) }) // ---------------------- // 数据源 // ---------------------- const categoryList = ref([ { label: '美食', value: 'food' }, { label: '旅游', value: 'travel' }, { label: '科技数码', value: 'tech' }, { label: '健身运动', value: 'fitness' }, { label: '学习提升', value: 'study' }, { label: '影视娱乐', value: 'entertainment' }, { label: '家居生活', value: 'lifestyle' } ]) // ---------------------- // 当前选中的 value // ---------------------- const selectedValue = ref('') // ---------------------- // 显示文本计算 // ---------------------- const displayText = computed(() => { const item = categoryList.value.find(item => item.value === selectedValue.value) return item ? item.label : '请选择...' }) // ---------------------- // ref 引用(关键!用于定位) // ---------------------- const triggerRef = ref(null) // ---------------------- // 获取组件实例(用于调用 open/close) // ---------------------- const dropdownMenuRef = ref(null) // ---------------------- // 方法:通过 ref 控制打开/关闭 // ---------------------- const callOpen = () => { if (dropdownMenuRef.value) { dropdownMenuRef.value.open() } else { console.warn('dropdownMenuRef 尚未挂载') } } const callClose = () => { if (dropdownMenuRef.value) { dropdownMenuRef.value.close() } } const resetSelection = () => { selectedValue.value = '' } // ---------------------- // 事件监听 // ---------------------- const handleChange = value => { console.log('【change】选中了:', value) uni.showToast({ title: `选择了: ${value}`, icon: 'none', duration: 1500 }) } const onOpen = val => { console.log('【open】下拉菜单已打开,当前值:', val) } const onClose = () => { console.log('【close】下拉菜单已关闭') } </script> <style scoped> .demo-container { padding: 40px 20px; background-color: #f9f9f9; min-height: 100vh; } .title { display: block; margin-bottom: 30px; font-size: 18px; font-weight: bold; color: #333; text-align: center; } .section { margin-bottom: 24px; } .label { display: block; margin-bottom: 8px; font-size: 16px; color: #555; } /* 触发器样式 */ .dropdown-trigger { display: flex; align-items: center; justify-content: space-between; width: 240px; height: 48px; padding: 0 16px; background-color: #ffffff; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05); font-size: 16px; color: #333; } .dropdown-trigger:active { background-color: #f5f5f5; } .trigger-text { flex: 1; text-align: left; } .arrow { font-size: 12px; color: #999; } /* 操作按钮 */ .action-box { display: flex; justify-content: space-around; margin: 30px 0; } .action-box button { font-size: 14px; padding: 8px 16px; background-color: #0f56d5; color: white; border-radius: 6px; } /* 结果展示 */ .result-box { margin-top: 20px; padding: 16px; background-color: #e8f4ff; border-radius: 8px; text-align: center; font-size: 15px; color: #0056b3; line-height: 1.6; } </style> [zy-popup-dropdown-menu] 未提供有效的 referenceRef
10-15
<!-- components/zy-popup-dropdown-menu.vue --> <template> <view> <!-- 触发元素插槽:支持自动绑定 open 方法 --> <slot name="reference" :open="open" :close="close" :toggle="toggle"> <!-- 默认触发器(可删除) --> <view v-if="!$slots.reference" data-reference @tap="open"> 点击选择 ▼ </view> </slot> <!-- 浮动下拉菜单 --> <view v-if="visible" ref="dropdownRef" class="zy-popup-dropdown-menu" :style="{ top: `${top}px`, left: `${left}px`, transform: position }" @touchmove.stop > <view class="dropdown-content"> <view v-for="item in props.data" :key="item[props.valueKey]" class="dropdown-item" :class="{ 'is-selected': props.modelValue === item[props.valueKey] }" @tap="handleSelect(item[props.valueKey])" > <text class="item-label">{{ item[props.labelKey] }}</text> <text v-if="props.modelValue === item[props.valueKey]" class="icon-check"></text> </view> </view> </view> </view> </template> <script setup> import { ref, nextTick, onUnmounted } from 'vue' // ---------------------- // Props // ---------------------- const props = defineProps({ data: { type: Array, required: true }, modelValue: { type: [String, Number, null], default: null }, labelKey: { type: String, default: 'label' }, valueKey: { type: String, default: 'value' }, // 接收外部传入的 ref referenceRef: { type: Object, default: null } }) // ---------------------- // Emits // ---------------------- const emit = defineEmits(['update:modelValue', 'change', 'open', 'close']) // ---------------------- // 内部状态 // ---------------------- const visible = ref(false) const top = ref(0) const left = ref(0) const position = ref('translateY(8px)') const dropdownRef = ref(null) const referenceRect = ref(null) // 缓存触发器位置 let observer = null // ---------------------- // 方法定义 // ---------------------- // 打开下拉框 const open = async () => { if (visible.value) return let rect = null if (props.referenceRef && props.referenceRef.$el) { // Vue 实例有 $el(H5 平台) rect = await getRectFromElement(props.referenceRef.$el) } else if (props.referenceRef?.el) { // uni-app 中 ref.el 是真实节点(App/小程序) rect = await getRectFromElement(props.referenceRef.el) } else { console.warn('[zy-popup-dropdown-menu] 未提供有效的 referenceRef') return } const res = await new Promise(resolve => { uni.createSelectorQuery().selectViewport().scrollOffset().exec(resolve) }) const scroll = res[0] const windowHeight = scroll.windowHeight || scroll.height const maxHeight = 486 const needUpward = windowHeight - rect.bottom < maxHeight left.value = rect.left top.value = needUpward ? rect.top - maxHeight - 8 : rect.bottom + 8 position.value = needUpward ? 'translateY(-8px)' : 'translateY(8px)' visible.value = true emit('open', props.modelValue) nextTick(() => { bindOutsideClickListener() bindScrollListener() }) } // 获取 DOM 元素 boundingClientRect function getRectFromElement(el) { return new Promise(resolve => { if (!el) return resolve(null) const query = uni.createSelectorQuery() query.select(`#${el.id}`).boundingClientRect() if (!el.id) { // 如果没有 id,尝试用临时 id el.id = 'temp-dropdown-trigger-' + Date.now() query.select(`#${el.id}`).boundingClientRect() setTimeout(() => { el.id = '' }, 100) // 清理 } query.exec(res => { resolve(res[0]) }) }) } // 关闭 const close = () => { if (!visible.value) return visible.value = false emit('close') removeListeners() } // 切换 const toggle = () => { visible.value ? close() : open() } // 选择项 const handleSelect = value => { if (props.modelValue !== value) { emit('update:modelValue', value) emit('change', value) } close() } // 外部点击关闭 const bindOutsideClickListener = () => { const handler = () => close() uni.$on('onPageTap', handler) observer = { ...observer, cleanupTap: () => uni.$off('onPageTap', handler) } } // 滚动关闭 const bindScrollListener = () => { const scrollHandler = () => close() uni.$on('onPageScroll', scrollHandler) observer = { ...observer, cleanupScroll: () => uni.$off('onPageScroll', scrollHandler) } } // 移除监听 const removeListeners = () => { observer?.cleanupTap?.() observer?.cleanupScroll?.() observer = null } // ---------------------- // 兼容性处理:thisContext 模拟 this // 因为 script setup 中没有 this,我们需要一个上下文对象 // 注意:HBuilderX 编译时会将组件实例注入到页面作用域 // 我们可以通过 getCurrentInstance 获取当前实例 uid,用于 in() import { getCurrentInstance } from 'vue' const instance = getCurrentInstance() const thisContext = instance.ctx || instance.proxy // ---------------------- // 暴露方法 // ---------------------- defineExpose({ open, close, toggle }) // ---------------------- // 卸载清理 // ---------------------- onUnmounted(() => { removeListeners() }) </script> <style scoped> /* 注意:给插槽外层加一个标记类名,便于查询 */ /* Vue 不直接支持 slot 元素样式,但我们可以在父级包裹或约定结构 */ /* 这里假设用户使用的元素会被包裹在一个具有特定结构的容器中 */ .zy-popup-dropdown-menu { position: fixed; width: 215px; max-height: 486px; background-color: #ffffff; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); z-index: 9999; overflow: hidden; } .dropdown-content { height: 100%; max-height: 486px; overflow-y: auto; -webkit-overflow-scrolling: touch; } .dropdown-item { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; font-size: 15px; color: #333333; border-bottom: 1px solid #f5f5f5; } .dropdown-item:last-child { border-bottom: none; } .dropdown-item.is-selected { color: #0f56d5; font-weight: 500; } .item-label { flex: 1; word-break: break-word; line-height: 1.4; text-align: left; } .icon-check { font-family: 'erda' !important; font-size: 16px; margin-left: 8px; color: #0f56d5; } </style> 给当前组件写一个完整的使用demo
10-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值