Vue3 Pinia国家城市联动下拉组件城市数据持续重载问题求助
问题描述
使用Vue 3结合Pinia Store开发国家与城市联动下拉组件时,每次选择国家后,城市数据会持续不断重载,无法停止。
相关代码
国家Store代码
import { defineStore } from "pinia"; import axios from "axios"; import router from "../../../router"; export const countryStore = defineStore("country", { state: () => ({ dataCountry: null, }), getters: { country: (state) => { state.dataCountry; // 缺少return语句 }, }, actions: { async getCountry() { const response = await axios.get("/api/get-country"); this.dataCountry = response.data.data; }, }, });
城市Store代码
import { defineStore } from "pinia"; import axios from "axios"; import router from "../../../router"; export const cityStore = defineStore("city", { state: () => ({ dataCity: null, }), getters: { city: (state) => { state.dataDistrict; // 引用不存在的state属性,且缺少return }, }, actions: { async getCity(value) { const response = await axios.get("/api/get-city?country=" + value); this.dataCity = response.data.data; }, }, });
Vue组件文件代码
<template> <div class="col-md-4"> <label for="country" class="form-label">Country</label> <Select2 id="country" v-model="form.countid" :options="countries.dataCountry" :change="listCities(form.countid)" /> </div> <div class="col-md-4"> <label for="city" class="form-label">City</label> <Select2 id="city" v-model="form.citid" :options="cities.dataCity" /> </div> </template> <script setup> import { ref, onMounted } from "vue"; import { countryStore } from "../stores/countryStore "; import { cityStore} from "../stores/cityStore"; import select2 from "select2"; select2(); const countries= countryStore (); const cities = cityStore(); const listCities = async (value) => { cities.dataCity(value); // 错误调用state属性作为方法 }; onMounted(async () => { countries.dataCountry(); // 错误调用state属性作为方法 // cities.dataCity(); }); </script>
问题原因及修复方案
核心问题点
- 事件绑定错误:组件中Select2的
change事件用了:change(属性绑定),会导致组件每次渲染都执行listCities,而非仅在选择变化时触发,造成无限循环请求。 - Store方法调用错误:组件错误调用Pinia的state属性作为方法(如
countries.dataCountry()),正确做法是调用Store定义的action方法(getCountry、getCity)。 - Getter定义错误:两个Store的getter都缺少
return语句,城市Store的getter还引用了不存在的state.dataDistrict,导致无法正确返回数据。 - 无重复请求拦截:未对相同国家的重复选择做判断,可能导致重复发起请求。
修复后的代码
修复后的国家Store
import { defineStore } from "pinia"; import axios from "axios"; import router from "../../../router"; export const countryStore = defineStore("country", { state: () => ({ dataCountry: null, }), getters: { country: (state) => { return state.dataCountry; // 添加return语句 }, }, actions: { async getCountry() { const response = await axios.get("/api/get-country"); this.dataCountry = response.data.data; }, }, });
修复后的城市Store
import { defineStore } from "pinia"; import axios from "axios"; import router from "../../../router"; export const cityStore = defineStore("city", { state: () => ({ dataCity: null, currentCountry: null, // 记录当前选中国家,拦截重复请求 }), getters: { city: (state) => { return state.dataCity; // 修正属性引用并添加return }, }, actions: { async getCity(value) { // 相同国家选择直接返回,避免重复请求 if (value === this.currentCountry) return; this.currentCountry = value; const response = await axios.get(`/api/get-city?country=${value}`); this.dataCity = response.data.data; }, }, });
修复后的Vue组件
<template> <div class="col-md-4"> <label for="country" class="form-label">国家</label> <!-- 改用@change绑定事件,而非属性绑定 --> <Select2 id="country" v-model="form.countid" :options="countries.dataCountry" @change="listCities" /> </div> <div class="col-md-4"> <label for="city" class="form-label">城市</label> <Select2 id="city" v-model="form.citid" :options="cities.dataCity" /> </div> </template> <script setup> import { ref, onMounted } from "vue"; import { countryStore } from "../stores/countryStore"; import { cityStore } from "../stores/cityStore"; import $ from "jquery"; // select2依赖jQuery,确保正确引入 import "select2"; const countries = countryStore(); const cities = cityStore(); // 初始化表单数据 const form = ref({ countid: "", citid: "" }); // 修正方法,通过事件参数获取选中值 const listCities = async (event) => { const selectedValue = event.target.value; await cities.getCity(selectedValue); // 调用正确的action方法 }; onMounted(async () => { await countries.getCountry(); // 调用正确的action方法加载国家列表 }); </script>
额外说明
- 确保使用的Select2组件支持Vue的
v-model和@change事件传递,若为第三方封装组件,需确认其事件命名规则(部分组件可能用@select而非@change)。
内容的提问来源于stack exchange,提问作者muhammad sumarno
相关产品推荐
相关产品推荐

