vue实现多级选择
Vue 实现多级选择的方法
使用递归组件实现多级选择
递归组件适合处理嵌套层级不确定的数据结构。定义一个组件,该组件能够调用自身来渲染子级选项。
<template>
<div>
<select v-model="selectedValue" @change="handleChange">
<option v-for="item in options" :value="item.value" :key="item.value">
{{ item.label }}
</option>
</select>
<recursive-select
v-if="selectedItem && selectedItem.children"
:options="selectedItem.children"
@selected="handleChildSelected"
/>
</div>
</template>
<script>
export default {
name: 'RecursiveSelect',
props: ['options'],
data() {
return {
selectedValue: null
}
},
computed: {
selectedItem() {
return this.options.find(item => item.value === this.selectedValue)
}
},
methods: {
handleChange() {
this.$emit('selected', this.selectedItem)
},
handleChildSelected(item) {
this.$emit('selected', item)
}
}
}
</script>
使用第三方组件库
Element UI、Ant Design Vue 等流行 UI 库提供了现成的级联选择器组件。

Element UI 示例:
<template>
<el-cascader
v-model="selectedOptions"
:options="options"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
selectedOptions: [],
options: [{
value: 'province1',
label: '省份1',
children: [{
value: 'city1',
label: '城市1'
}]
}]
}
},
methods: {
handleChange(value) {
console.log(value)
}
}
}
</script>
使用动态组件加载
对于性能要求较高的场景,可以动态加载下一级选项数据,而不是一次性加载所有层级。

<template>
<div>
<select v-model="level1" @change="loadLevel2">
<option v-for="item in level1Options" :value="item.id" :key="item.id">
{{ item.name }}
</option>
</select>
<select v-model="level2" @change="loadLevel3" v-if="level2Options.length">
<option v-for="item in level2Options" :value="item.id" :key="item.id">
{{ item.name }}
</option>
</select>
<select v-model="level3" v-if="level3Options.length">
<option v-for="item in level3Options" :value="item.id" :key="item.id">
{{ item.name }}
</option>
</select>
</div>
</template>
<script>
export default {
data() {
return {
level1: null,
level2: null,
level3: null,
level1Options: [],
level2Options: [],
level3Options: []
}
},
async created() {
this.level1Options = await this.fetchData('level1')
},
methods: {
async loadLevel2() {
this.level2Options = await this.fetchData(`level2?parent=${this.level1}`)
this.level2 = null
this.level3Options = []
},
async loadLevel3() {
this.level3Options = await this.fetchData(`level3?parent=${this.level2}`)
this.level3 = null
},
fetchData(url) {
return axios.get(url).then(res => res.data)
}
}
}
</script>
使用 Vuex 管理状态
对于复杂应用,可以使用 Vuex 集中管理多级选择的状态和数据。
// store.js
export default new Vuex.Store({
state: {
selections: {
level1: null,
level2: null,
level3: null
},
options: {
level1: [],
level2: [],
level3: []
}
},
mutations: {
setSelection(state, { level, value }) {
state.selections[level] = value
},
setOptions(state, { level, options }) {
state.options[level] = options
}
},
actions: {
async fetchOptions({ commit }, { level, parent }) {
const options = await axios.get(`api/${level}?parent=${parent}`)
commit('setOptions', { level, options })
}
}
})
使用组合式 API (Vue 3)
Vue 3 的组合式 API 可以更灵活地组织多级选择逻辑。
<template>
<div v-for="(level, index) in levels" :key="index">
<select v-model="selections[index]" @change="loadNextLevel(index)">
<option value="">请选择</option>
<option v-for="item in level.options" :value="item.value" :key="item.value">
{{ item.label }}
</option>
</select>
</div>
</template>
<script>
import { reactive, ref } from 'vue'
export default {
setup() {
const levels = reactive([
{ options: [], loaded: false },
{ options: [], loaded: false },
{ options: [], loaded: false }
])
const selections = ref([null, null, null])
const loadLevel = async (index, parentId) => {
const res = await fetch(`/api/level${index + 1}?parent=${parentId}`)
levels[index].options = await res.json()
levels[index].loaded = true
}
const loadNextLevel = (index) => {
if (index < levels.length - 1 && selections.value[index]) {
loadLevel(index + 1, selections.value[index])
selections.value[index + 1] = null
}
}
// 初始化加载第一级
loadLevel(0)
return { levels, selections, loadNextLevel }
}
}
</script>
以上方法可根据具体需求选择使用,递归组件适合简单嵌套结构,动态加载适合大数据量场景,第三方组件库提供开箱即用的解决方案,Vuex 适合复杂状态管理,组合式 API 提供更灵活的代码组织方式。






