子组件
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)"中可以写两条语句,用分号分隔。这是组件通信的重点。