封装一个下拉单选组件
有些时候需要用到单选功能,使用单选框太占位置了。
@/components/selector.vue
<script setup lang="ts">
import SvgIcon from "@/components/svgIcon/index.vue"
import { ref } from "vue"
import type { SelectorData } from "@/components/selector/type"
defineOptions({ name: "Selector" })
// 是否显示下拉内容
const show = ref(false)
// 已选择的值
const showValue = ref("")
interface SelectorProps {
placeholder?: string
data: SelectorData[]
}
const props = defineProps<SelectorProps>()
const modelValue = defineModel<string | number | undefined>({
default: "",
})
if (modelValue.value) {
const current = props.data.find((item) => {
return item.id === modelValue.value
})
if (current) {
showValue.value = current.name
}
}
// 选中改变
const changeSelect = (item: SelectorData) => {
showValue.value = item.name
modelValue.value = item.id
}
</script>
<template>
<div class="selector" @click="show = !show" :class="{show}">
<span class="value" :class="{placeholder: modelValue === ''}">
{{ showValue || placeholder || '请选择...' }}
</span>
<SvgIcon
class="right-icon"
:name="show ? 'arrow-up' : 'arrow-down'"
></SvgIcon>
<div class="drop-list" :class="{show}">
<ul>
<li v-for="item in data" :key="item.id" @click="changeSelect(item)">
{{item.name}}
</li>
</ul>
</div>
</div>
</template>
<style scoped lang="scss">
.selector {
min-width: 200px;
height: 40px;
border: 2px dashed #ccc;
border-radius: 5px;
position: relative;
padding: 0 10px;
line-height: 40px;
cursor: pointer;
display: flex;
align-items: center;
.value {
flex: 1;
&.placeholder {
color: #808080;
}
}
.right-icon {
margin-left: 10px;
}
&.show {
border-bottom-color: transparent;
}
.drop-list {
position: absolute;
top: 40px;
left: 0;
width: 100%;
background-color: #fff;
visibility: hidden;
box-shadow: 0 0 4px #eee;
border-left: 2px solid #eee;
border-right: 2px solid #eee;
border-bottom: 2px solid #eee;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
&.show {
visibility: visible;
}
ul li {
padding: 0 10px;
border-bottom: 1px solid #ccc;
&:last-child {
border-bottom: none;
}
&:hover {
color: $primary-color;
}
}
}
}
</style>
ts 类型
export interface SelectorData {
id: number
name: string
}