Vue.js 中实现州-城市级联下拉选及城市加载失败问题排查
联动下拉失效问题修复方案
核心失效原因
- 最关键的bug:
listCities方法调用接口拿到响应后,没有把返回的城市列表赋值给组件的cities响应式变量,导致下拉框始终绑定空数组,自然没有可选选项 - 缺少切州时的重置逻辑:切换州时没有清空之前选中的城市值和旧城市列表,容易残留跨州的无效选中值
- 缺少交互兜底:未选州时城市下拉没有禁用态,也没有占位提示,用户体验割裂
- 城市请求没有对齐已有的错误处理逻辑,接口异常时无反馈
修正实现步骤
- 补全
listCities方法的响应赋值逻辑,对齐listStates的错误处理流程 - 触发州切换事件时,先清空旧的城市列表、重置城市选中值,避免脏数据
- 增加前置判断:未选中州时直接中断城市请求,不发送无效查询
- 优化下拉框交互:未选州时城市下拉置灰禁用,增加加载提示和默认占位选项
修正后的脚本代码
export default { data() { return { loading: false, inscription: new InscriptionModel(), successful: false, message: '', arrProfiles: [], arrStatus: [], states: [], cities: [], }; }, async mounted() { this.states = await this.listStates(); }, methods: { async listStates() { const response = await api.post('graphql', { query: ` query{ listStates{ data { id, name, uf } } } `, }); if (Helpers.hasProperty(response.data, 'errors')) { Helpers.getValidateException(response.data); return; } return response.data.data.listStates.data; }, async listCities() { // 切换州时先重置旧数据 this.cities = [] this.inscription.cities = '' // 未选中州直接终止请求 if (!this.inscription.state) return this.loading = true try { const response = await api.post('graphql', { query: ` query{ listCities(condition: {state_id: ${this.inscription.state}}) { data { id, name } } } `, }); // 对齐已有错误处理逻辑 if (Helpers.hasProperty(response.data, 'errors')) { Helpers.getValidateException(response.data); return; } // 关键:将接口返回的城市列表赋值给响应式变量,驱动下拉渲染 this.cities = response.data.data.listCities.data } finally { this.loading = false } } } }
修正后的模板代码
<div class="col-sm-12 col-md-6 col-lg-3 col-xl-3"> <div class="form-group"> <label for="state_id">State</label> <select name="state" id="state_id" class="custom-select" @change="listCities()" v-model="inscription.state" > <option value="" disabled>请选择州</option> <option v-for="state in states" v-bind:value="state.id" :key="state.id"> {{ state.name }} </option> </select> </div> </div> <div class="col-sm-12 col-md-6 col-lg-3 col-xl-3"> <div class="form-group"> <label for="city_id">City</label> <select id="citie" v-model="inscription.cities" class="custom-select" :disabled="!inscription.state" > <option value="" disabled>{{ loading ? '城市加载中...' : '请先选择州' }}</option> <option v-for="citie in cities" v-bind:value="citie.id" :key="citie.id"> {{ citie.name }} </option> </select> </div> </div>
内容的提问来源于stack exchange,提问作者testCode
相关产品推荐
相关产品推荐

