You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

问题原因及修复方案

核心问题点

  1. 事件绑定错误:组件中Select2的change事件用了:change(属性绑定),会导致组件每次渲染都执行listCities,而非仅在选择变化时触发,造成无限循环请求。
  2. Store方法调用错误:组件错误调用Pinia的state属性作为方法(如countries.dataCountry()),正确做法是调用Store定义的action方法(getCountry、getCity)。
  3. Getter定义错误:两个Store的getter都缺少return语句,城市Store的getter还引用了不存在的state.dataDistrict,导致无法正确返回数据。
  4. 无重复请求拦截:未对相同国家的重复选择做判断,可能导致重复发起请求。

修复后的代码

修复后的国家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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:36:03