Vue将单选下拉类型筛选改造为复选框多选筛选
单类型下拉改多选复选框筛选实现
核心改动逻辑
- 数据层调整:把原来存单选值的字符串类型
selectedType替换为数组类型selectedTypes,默认值为空数组,用来存储所有勾选的类型值;额外新增可选类型列表typeOptions,当前版本内置选项,后续对接axios拉取独立JSON数据时,只需要把请求返回的类型列表赋值给这个字段即可,无需改动核心筛选逻辑。 - 视图层调整:移除原有的
<select>单选下拉,替换为复选框组,每个复选框绑定对应类型值,通过v-model和selectedTypes数组双向绑定。 - 筛选逻辑调整:原有的单值相等判断改为数组包含判断:当选中类型数组为空时,不做类型筛选;当有选中值时,判断列表项的type值是否在选中数组内,保留匹配项。该逻辑同时兼容后续列表项配置多类型属性的扩展需求,只需要把判断逻辑调整为「列表项的type数组和选中数组是否存在交集」即可。
完整可运行代码
JS 逻辑部分
new Vue({ el: '#app', data: { selectedTypes: [], // 改为数组存储多选的类型 startDate: null, endDate: null, // 可选类型列表,后续axios请求数据时直接替换该数组内容即可 typeOptions: [ { value: 'mercedes', label: 'Mercedes' }, { value: 'bmw', label: 'BMW' } ], items: [ { name: 'Nolan', type: 'mercedes', year: '2020', country: 'england', date: '08/01/2020' }, { name: 'Edgar', type: 'bmw', year: '2020', country:'belgium', date: '08/11/2020' }, { name: 'John', type: 'bmw', year: '2019', country: 'england', date: '08/21/2020' }, { name: 'Axel', type: 'mercedes', year: '2020', country: 'england', date: '08/01/2020' } ] }, computed: { filterItem: function () { const selectedTypes = this.selectedTypes let startDate = this.startDate && new Date(this.startDate); let endDate = this.endDate && new Date(this.endDate); return this.items.filter(item => { // 类型筛选:没选类型直接返回true,选了就判断当前项类型是否在选中列表里 const typeMatch = selectedTypes.length === 0 ? true : selectedTypes.includes(item.type) if (!typeMatch) return false // 原有日期筛选逻辑保持不变 const itemDate = new Date(item.date) if (startDate && endDate) { return startDate <= itemDate && itemDate <= endDate; } if (startDate && !endDate) { return startDate <= itemDate; } if (!startDate && endDate) { return itemDate <= endDate; } return true; }) } }, // 后续对接axios参考写法,直接替换对应data值即可 // created() { // axios.get('/your-data.json').then(res => { // this.items = res.data.items // this.typeOptions = res.data.typeOptions // }) // } })
CSS 样式部分
.list-item { margin-top: 50px; } #app { position: relative; padding-bottom: 200px; } span { margin: 0 15px; cursor: pointer; } .filter-box { margin-top: 15px; } .card { box-shadow: 0px 10px 16px rgba(0, 0, 0, 0.16); width: 400px; padding: 20px 30px; margin-bottom: 30px; } button { background-color: #1cf478; border: none; padding: 10px 25px; font-weight: bold; border-radius: 15px; } select,input { border: none; padding: 10px 15px; background-color: #c1c1c1; border-radius: 10px; } /* 新增复选框组样式 */ .type-filter-group { display: inline-flex; gap: 12px; margin: 0 10px; vertical-align: middle; } .type-filter-group label { cursor: pointer; }
HTML 模板部分
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <label>Type</label> <!-- 替换原来的select为复选框组 --> <div class="type-filter-group"> <label v-for="option in typeOptions" :key="option.value"> <input type="checkbox" :value="option.value" v-model="selectedTypes"> {{ option.label }} </label> </div> <label>From</label> <input type="date" v-model="startDate"> <label>To</label> <input type="date" v-model="endDate"> <div class="list-item" v-for="item in filterItem" :key="item.name"> <div class="card"> <p>Name: {{ item.name }}</p> <p>Car: {{ item.type }}</p> <p>Date: {{ item.date }}</p> <p>Country: {{ item.country }}</p> </div> </div> </div>
扩展说明
- 当前版本完全适配现有内置单类型JSON数据,不需要修改原有items的结构即可运行。
- 后续需要支持列表项多类型属性时,只需要把item的type字段改为数组格式(例如
type: ['mercedes', 'bmw']),将类型匹配逻辑替换为selectedTypes.some(t => item.type.includes(t))即可。 - 对接axios请求独立JSON文件时,只需要在组件的
created/mounted生命周期中发起请求,将返回的items、typeOptions分别赋值给对应data字段即可,筛选逻辑不需要做任何修改。
内容的提问来源于stack exchange,提问作者Crashdesk
相关产品推荐
相关产品推荐

