vue项目实现排他功能
Vue 项目实现排他功能的方法
排他功能通常指在多个选项中只能选择一个,其他选项自动取消选中状态。以下是几种常见的实现方式:
使用 v-model 和计算属性
通过 v-model 绑定同一个变量,利用计算属性或方法实现排他逻辑:
<template>
<div>
<button
v-for="option in options"
:key="option"
@click="selectOption(option)"
:class="{ active: selectedOption === option }"
>
{{ option }}
</button>
</div>
</template>
<script>
export default {
data() {
return {
options: ['Option 1', 'Option 2', 'Option 3'],
selectedOption: null
}
},
methods: {
selectOption(option) {
this.selectedOption = option === this.selectedOption ? null : option
}
}
}
</script>
使用单选按钮组
利用原生 radio input 的排他特性,通过 v-model 绑定:
<template>
<div>
<label v-for="option in options" :key="option">
<input
type="radio"
:value="option"
v-model="selectedOption"
>
{{ option }}
</label>
</div>
</template>
<script>
export default {
data() {
return {
options: ['Option A', 'Option B', 'Option C'],
selectedOption: null
}
}
}
</script>
使用 Vuex 管理状态
对于复杂应用,可以通过 Vuex 集中管理选中状态:
// store.js
export default new Vuex.Store({
state: {
selectedItem: null
},
mutations: {
setSelectedItem(state, payload) {
state.selectedItem = payload
}
}
})
<template>
<div>
<div
v-for="item in items"
:key="item.id"
@click="selectItem(item)"
:class="{ active: isSelected(item) }"
>
{{ item.name }}
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['selectedItem']),
isSelected() {
return item => item.id === this.selectedItem?.id
}
},
methods: {
...mapMutations(['setSelectedItem']),
selectItem(item) {
this.setSelectedItem(item)
}
}
}
</script>
自定义指令实现
创建自定义指令处理排他逻辑:
// main.js
Vue.directive('exclusive', {
bind(el, binding, vnode) {
el._exclusiveHandler = () => {
const group = binding.value
group.selected = el.dataset.value
}
el.addEventListener('click', el._exclusiveHandler)
},
unbind(el) {
el.removeEventListener('click', el._exclusiveHandler)
}
})
<template>
<div>
<button
v-for="opt in options"
:key="opt"
v-exclusive="exclusiveGroup"
:data-value="opt"
:class="{ active: exclusiveGroup.selected === opt }"
>
{{ opt }}
</button>
</div>
</template>
<script>
export default {
data() {
return {
options: ['X', 'Y', 'Z'],
exclusiveGroup: { selected: null }
}
}
}
</script>
注意事项
- 性能考虑:对于大型列表,使用 v-show 而非 v-if 避免频繁 DOM 操作
- 无障碍访问:使用 radio 时确保正确的 label 关联
- 移动端适配:可添加触摸事件支持
- 动画效果:可结合 transition 组件实现平滑的选中状态切换
以上方法可根据具体场景选择使用,简单交互推荐前两种方案,复杂状态管理建议使用 Vuex。







