vue3 下拉菜单

子组件

html 复制代码
<template>
    <div>
        <div class="m-input" @click.stop="isopen = !isopen">
            {{ selectedLabel || '请选择' }}
            <span class="arrow" :class="{up:isopen}">▼</span>
        </div>
        <div class="m-show" v-if="isopen">
            <div class="m-item" v-for="val in items" @click.stop="seletitem(val);$emit('open-change',selectedValue)"
                :class="{ active: selectedValue === val.value }">{{ val.label }}</div>
        </div>
    </div>





</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';



const selectedLabel = ref('')
const selectedValue = ref('')
const isopen = ref(false)
const items = [
    { label: '苹果', value: 'apple' },
    { label: '香蕉', value: 'banana' },
    { label: '橙子', value: 'orange' },
]

const seletitem = (item) => {
    selectedLabel.value = item.label
    selectedValue.value = item.value
    isopen.value = false
}

onMounted(() => {
    document.addEventListener('click', handleDocClick)
})

onUnmounted(() => {
    document.removeEventListener('click', handleDocClick)
})

//全局点击关闭下拉
const handleDocClick = () => {
    isopen.value = false
}


</script>

<style scoped>
.m-input {
    width: 200px;
    font-size: 14px;
    padding: 10px;
    border: 1px solid #dadada;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;

}

.m-input:hover {
    cursor: pointer;
    border: 1px solid #7ff3e4;

}

.m-show {
    width: 220px;
    height: auto;
    border: 1px solid #ccc;
}

.active {
    background-color: azure;
    color: #157e70;
}

.arrow {
  font-size: 10px;
  transition: transform 0.2s;
}
.arrow.up {
  transform: rotate(180deg);
}



.m-item {
    padding: 10px;
    font-size: 14px;
}

.m-item:hover {

    background-color: rgb(190, 255, 255);
    cursor: pointer;
}
</style>

父组件

html 复制代码
<template>
  
<Menu2 @open-change="getvalue"/>
<br>


</template>

<script setup>
import Menu2 from './views/Menu2.vue';

function getvalue(val){
  console.log(val)

}
</script>

<style scoped>

.ceshi{
  height: 20px;
  width:20px
}

</style>

知识点:

@click.stop="seletitem(val);$emit('open-change',selectedValue)"中可以写两条语句,用分号分隔。这是组件通信的重点。

相关推荐
光锥智能1 分钟前
海康机器人举行2026移动机器人新品发布会:箱式存拣升级,「明智」系列发布
java·前端·机器人
计算机魔术师2 分钟前
Anthropic 上市文件最吓人的一幕,不是亏损 807 亿
前端
alsmile13 分钟前
AI友好的可视化图形引擎自我革命:Meta2d.js 2.0 历时一年全新重写,性能与多人协作全面升级
前端·开源·数据可视化
行思理13 分钟前
Nginx 跨站请求(CORS)配置完全指南:从原理到生产实践
java·前端·nginx
粥里有勺糖34 分钟前
视野修炼-技术周刊第137期 | 编程已经面目全非
前端·github·ai编程
IT_陈寒44 分钟前
Python的列表推导式用不好真的会爆内存你知道吗
前端·人工智能·后端
moshuying1 小时前
块扩散 + GDN 改造:Clover 把「并行生成」塞进了 Agent 的长上下文里
前端·算法
kyriewen1 小时前
我算了笔账:AI 编程工具一年烧掉两台 MacBook
前端·人工智能·程序员
moshuying2 小时前
扩散模型开始写代码、开网页了:350 亿参数,速度比 Jev 快一倍
前端·算法
qq_401700412 小时前
100 个 IoT 小项目,给 ESP32 入门补上实操
前端·网络·stm32