Skip to content

Vue3使用普通div标签实现单选以及多选效果

为什么要这么做?

今天做一个点餐的H5网页有这么一个需求,在浏览商品时由于一些商品存在定制情况,比如大份、中份或者选择套餐等。因此首先我考虑使用单选按钮以及多选按钮来实现这个需求,但是实现出来的效果跟UI设计稿大相径庭,这是因为组件库中的单选以及多选都有特定的样式,因此并不能满足需求,修改组件库的按钮样式又过于麻烦,因此决定自己来实现这一效果。

设计与实现

设计

单选

单选的效果很容易实现,我们只需要声明一个变量currentIndex,然后在循环遍历数据时使用currentIndex与循环时的index进行比较,如果想要一开始就有选中的默认效果currentIndex = 0,如果不想要默认效果,那么currentIndex可以设置为-1。

多选

如果想要实现多选,我们就不能像做单选那样仅仅声明一个基本数据类型的变量来保存当前的选中项了,因此我们需要一个数组来保存我们所选中的所有选项。然后在循环时判断当前选项是否在我们声明的数组当中,是,则选中。

如何表示选中?

在公司的项目中我使用的是tailwindcss的方式,如果下标相同或者数组中有这一选项则给他加一个类样式,但是考虑到最终样式覆盖的问题,因此最后才采取的是动态添加style属性的方案来设置选中后以及选中前的颜色,其余的使用tailwindcss

实现

vue
// 单选
<script setup lang='ts'>
const radioOptions = ref<string[]>(['大', '中', '小'])

const currentIndex = 0
const selectRadioOptions = (index: number) => {
    currentIndex.value = index
}
</script>

<template>
    <div class="container flex">
        <template v-for="(item, index) in radioOptions" :key="index">
            <div 
                 class="border flex-1 text-center mr-2 text-sm p-1.5 rounded-[5px]" 
                 :style="{ 
                     color: currentIndex === index ? 'white' : 'black'
                    'background-color': currentIndex === index ? 'red' : 'white'
                 }"
                 @click="selectRadioOptions(index)"
            >
                {{ item }}
            </div>

        </template>

    </div>

</template>
vue
// 多选
<script lang="ts" setup>
const options = ref<string[]>(['甜点', '蛋糕', '宫保鸡丁'])
const selectedOptions = ref<string[]>([])
const selectMultipleOptions = (item: string) => {
    selectedOptions.value.push(item)
}
</script>

<template>
    <div class="container flex">
        <template v-for="(item, index) in options" :key="index">
            <div 
                 class="border flex-1 text-center mr-2 text-sm p-1.5 rounded-[5px]"
                 :style="{ 
                     color: selectedOptions.includes(item) ? 'white' : 'black'
                    'background-color': selectedOptions.includes(item) ? 'red' : 'white'
                 }"
                 @click="selectMultipleOptions(item)"
            >
                {{ item }}
            </div>

        </template>

    </div>

</template>