vue列表多选实现思路
Vue列表多选实现思路
基础实现:v-model绑定数组
通过v-model绑定一个数组,配合checkbox的value属性实现多选。选中时自动将值添加到数组,取消选中时从数组中移除。

<template>
<div>
<div v-for="item in list" :key="item.id">
<input
type="checkbox"
:id="item.id"
:value="item.value"
v-model="selectedItems"
>
<label :for="item.id">{{ item.label }}</label>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: '1', value: 'apple', label: 'Apple' },
{ id: '2', value: 'banana', label: 'Banana' },
{ id: '3', value: 'orange', label: 'Orange' }
],
selectedItems: []
}
}
}
</script>
自定义组件实现
封装可复用的多选列表组件,通过props接收选项列表,通过emit事件返回选中值。

<template>
<div>
<div v-for="item in options" :key="item.id">
<input
type="checkbox"
:id="item.id"
:value="item.value"
v-model="internalSelected"
@change="handleChange"
>
<label :for="item.id">{{ item.label }}</label>
</div>
</div>
</template>
<script>
export default {
props: {
options: Array,
value: Array
},
data() {
return {
internalSelected: this.value || []
}
},
methods: {
handleChange() {
this.$emit('input', this.internalSelected)
}
}
}
</script>
表格行多选
结合表格实现行选择功能,通常需要配合selection样式和全选功能。
<template>
<div>
<table>
<thead>
<tr>
<th><input type="checkbox" v-model="selectAll"></th>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in tableData" :key="index">
<td><input type="checkbox" v-model="selectedRows" :value="item"></td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{ name: 'John', age: 25 },
{ name: 'Jane', age: 22 },
{ name: 'Doe', age: 30 }
],
selectedRows: [],
selectAll: false
}
},
watch: {
selectAll(val) {
this.selectedRows = val ? [...this.tableData] : []
}
}
}
</script>
虚拟列表优化
对于大数据量列表,结合虚拟滚动技术优化性能,只渲染可视区域内的选项。
<template>
<div class="virtual-list" @scroll="handleScroll">
<div class="list-phantom" :style="{ height: totalHeight + 'px' }"></div>
<div class="list-content" :style="{ transform: `translateY(${startOffset}px)` }">
<div
v-for="item in visibleData"
:key="item.id"
class="list-item"
>
<input type="checkbox" v-model="selectedItems" :value="item.value">
<span>{{ item.label }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
listData: Array,
itemHeight: Number
},
data() {
return {
startIndex: 0,
endIndex: 20,
screenHeight: 500,
selectedItems: []
}
},
computed: {
totalHeight() {
return this.listData.length * this.itemHeight
},
visibleData() {
return this.listData.slice(this.startIndex, this.endIndex)
},
startOffset() {
return this.startIndex * this.itemHeight
}
},
methods: {
handleScroll(e) {
const scrollTop = e.target.scrollTop
this.startIndex = Math.floor(scrollTop / this.itemHeight)
this.endIndex = this.startIndex + Math.ceil(this.screenHeight / this.itemHeight)
}
}
}
</script>
注意事项
- 大数据量情况下避免直接使用
v-for渲染所有选项,考虑分页或虚拟滚动 - 选中状态管理应使用Vue响应式数据,避免直接操作DOM
- 自定义组件时注意实现
v-model的双向绑定协议 - 移动端适配可能需要特殊处理触摸事件和选择样式






