Pinia Getters 通过分步计算省市区层级路径实现响应式、可缓存的派生状态,支持动态筛选与跨 store 联动,并需避免返回新对象、副作用及过度耦合。

Pinia Getters 处理省市区联动路径计算,核心是把“层级关系”和“当前选择”转化为可响应、可缓存的派生状态,而不是在组件里反复遍历或手动拼接。关键不在于“怎么写一个函数”,而在于“怎么组织依赖、避免重复、支持动态切换”。
用 getter 拆解层级路径:省 → 市 → 区
假设 state 中有 provinces(省列表)、currentProvinceCode、currentCityCode、currentDistrictCode 三个字段,路径计算就该分步实现:
- 当前省信息:province: (state) => state.provinces.find(p => p.code === state.currentProvinceCode) || null
- 当前市列表(依赖省):cities: (state) => { const p = state.provinces.find(p => p.code === state.currentProvinceCode); return p?.cities || [] }
- 当前市信息:city: (state) => state.cities.find(c => c.code === state.currentCityCode) || null
- 当前区列表(依赖市):districts: (state) => { const c = state.cities.find(c => c.code === state.currentCityCode); return c?.districts || [] }
- 完整路径文本:fullPath: (state) => [state.province?.name, state.city?.name, state.districts.find(d => d.code === state.currentDistrictCode)?.name].filter(Boolean).join(' / ')}
支持动态筛选的 getter:按省查市、按市查区
如果需要在下拉中实时过滤(比如搜索框输入“杭”查杭州相关城市),getter 应返回函数,但要注意缓存策略:
- 写法:citiesByKeyword: (state) => (keyword) => state.cities.filter(c => c.name.includes(keyword))
- 调用:
store.citiesByKeyword('杭') - 注意:Pinia 不会为不同 keyword 缓存结果。高频使用时建议封装 memoize,例如:
import { memoize } from 'lodash'; citiesByKeyword: (state) => memoize((keyword) => state.cities.filter(...))
跨 store 联动:当省市区数据来自不同模块
比如 provinces 存在 useAreaStore,用户最近选择存在 useUserStore,可在 getter 中显式调用:
- 导入:
import { useAreaStore } from '@/stores/area' - getter 内部:
lastSelectedPath() { const area = useAreaStore(); const user = useUserStore(); const p = area.provinces.find(x => x.code === user.lastProvince); const c = p?.cities.find(y => y.code === user.lastCity); return [p?.name, c?.name].filter(Boolean).join(' > ') } - Pinia 会自动追踪 useAreaStore 和 useUserStore 的变化,只要任一依赖更新,该 getter 就重算
避免常见陷阱:路径失效或重复渲染
路径计算容易出问题的地方不在逻辑,而在响应式细节:
- 不要在 getter 里直接返回新对象:
() => ({ province: state.province })—— 每次都是新引用,导致组件误判为变更;应改用provinceName: (state) => state.province?.name || '' - 避免副作用:不要在 getter 里发请求、读 Date.now() 或 localStorage,这会让缓存失效且不可预测
- 复杂路径建议拆成小 getter:比如先算
selectedProvince,再算availableCities,最后组合pathLabel,Pinia 可分别缓存每一步,比一个大函数更高效


















