vue实现选座
Vue 实现选座功能
选座功能常见于影院、演出、交通等场景,以下是基于 Vue 的实现方案:
数据结构设计
使用二维数组表示座位布局,每个座位包含状态属性(如可选、已选、已售):

data() {
return {
seats: [
[{status: 'available'}, {status: 'sold'}],
[{status: 'available'}, {status: 'available'}]
],
selectedSeats: []
}
}
座位渲染
通过嵌套 v-for 渲染座位矩阵,动态绑定样式类:

<div v-for="(row, rowIndex) in seats" :key="rowIndex" class="seat-row">
<div
v-for="(seat, colIndex) in row"
:key="colIndex"
:class="['seat', seat.status]"
@click="selectSeat(rowIndex, colIndex)"
>
{{ rowIndex + 1 }}-{{ colIndex + 1 }}
</div>
</div>
选择逻辑实现
处理座位点击事件,更新状态和选中列表:
methods: {
selectSeat(row, col) {
if (this.seats[row][col].status === 'sold') return;
const seatKey = `${row}-${col}`;
if (this.selectedSeats.includes(seatKey)) {
this.seats[row][col].status = 'available';
this.selectedSeats = this.selectedSeats.filter(k => k !== seatKey);
} else {
this.seats[row][col].status = 'selected';
this.selectedSeats.push(seatKey);
}
}
}
样式设计
通过 CSS 区分不同状态:
.seat {
width: 30px;
height: 30px;
margin: 5px;
display: inline-flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.available { background: #4CAF50; }
.selected { background: #FFC107; }
.sold { background: #F44336; cursor: not-allowed; }
优化建议
- 添加屏幕区域标识(如荧幕位置)
- 实现最大可选数量限制
- 加入座位类型区分(如VIP座)
- 使用 Vuex 管理复杂状态
- 增加选座确认和反选功能
完整组件示例
<template>
<div class="seat-map">
<div class="screen">荧幕</div>
<div v-for="(row, rowIndex) in seats" :key="rowIndex" class="seat-row">
<div
v-for="(seat, colIndex) in row"
:key="colIndex"
:class="['seat', seat.status, seat.type]"
@click="handleSeatClick(rowIndex, colIndex)"
>
{{ rowIndex + 1 }}-{{ colIndex + 1 }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
maxSelection: 5,
seats: [
[
{status: 'available', type: 'standard'},
{status: 'available', type: 'vip'}
],
[
{status: 'sold', type: 'standard'},
{status: 'available', type: 'standard'}
]
]
}
},
methods: {
handleSeatClick(row, col) {
const seat = this.seats[row][col];
if (seat.status === 'sold') return;
seat.status = seat.status === 'selected' ? 'available' : 'selected';
this.$emit('selection-change', this.getSelectedSeats());
},
getSelectedSeats() {
return this.seats.flatMap((row, rowIndex) =>
row.map((seat, colIndex) =>
seat.status === 'selected' ? `${rowIndex}-${colIndex}` : null
).filter(Boolean)
);
}
}
}
</script>






