Vue3中使用Pinia实现API数据搜索与筛选功能的技术问询
Vue3中使用Pinia实现API数据搜索与筛选功能的技术问询
看起来你已经走完了数据拉取和基础展示的流程,遇到的Pinia数据获取、筛选逻辑问题,我来帮你一步步梳理解决思路~
首先解决组件内无法获取Pinia数据的问题
你代码里的问题大概率是没保持数据响应式或者重复创建Store实例导致的,咱们先把Store定义和组件用法修正过来:
第一步:规范定义Pinia Store
先创建一个结构清晰的Store文件,比如stores/testStore.js:
import { defineStore } from 'pinia' export const useTestStore = defineStore('test', { // 初始化状态,必须给receivedData设空数组默认值 state: () => ({ receivedData: [], // 新增筛选条件状态,存用户选择的过滤器值 filterConditions: { name: '', location: '', // 可添加侧边栏其他筛选字段,比如类型、状态等 } }), actions: { // 存储API返回的全量数据 addData(data) { this.receivedData = data }, // 增量更新筛选条件 updateFilterConditions(newConditions) { this.filterConditions = { ...this.filterConditions, ...newConditions } }, // 重置筛选条件,用于搜索按钮点击后显示全列表 resetFilters() { this.filterConditions = { name: '', location: '' // 其他字段同步重置为空 } } }, getters: { // 核心:根据筛选条件自动返回过滤后的列表,响应状态变化 filteredData: (state) => { return state.receivedData.filter(item => { let isMatch = true // 匹配名称筛选条件 if (state.filterConditions.name && item.name !== state.filterConditions.name) { isMatch = false } // 匹配位置筛选条件 if (state.filterConditions.location && item.location !== state.filterConditions.location) { isMatch = false } // 其他筛选字段可在此添加判断逻辑 return isMatch }) } } })
第二步:组件内正确使用Store
在页面组件里,用storeToRefs保持数据响应式,避免重复创建Store实例:
import { useTestStore } from '@/stores/testStore' import { storeToRefs } from 'pinia' import axios from 'axios' // 只创建一次Store实例 const testStore = useTestStore() // 用storeToRefs解构响应式的状态和计算属性 const { receivedData, filteredData } = storeToRefs(testStore) // 解构Store里的方法 const { addData, updateFilterConditions, resetFilters } = testStore async function getList(docName, docLocation) { try { console.info(docName + ' ' + docLocation) // 用axios的params参数拼接url更规范,避免手动拼接出错 const { data } = await axios.get('http://127.0.0.1:5000/doc_list', { params: { search: docLocation, name: docName } }) if (data.error_message) { console.log(data.error_message) } else { addData(data.data) // 将API数据存入Store const reg = "(?:[01]\\d|2[0123]):(?:[012345]\\d):(?:[012345]\\d)" console.log((data.data[0].apts_id[0].time).match(reg)[0]) } } catch (error) { console.log(error.message); } }
实现搜索与筛选的核心功能
基础问题解决后,咱们来实现你要的功能逻辑:
1. 点击搜索按钮显示全列表
根据需求选择两种逻辑之一:
- 需要重新从后端拉取最新数据并显示全列表:
async function handleSearch() { // 假设你有输入框绑定的searchName、searchLocation变量 await getList(searchName.value, searchLocation.value) // 重置筛选条件,确保显示全量新数据 resetFilters() }
- 已有本地数据,仅显示全列表无需重新拉取:
function handleSearch() { resetFilters() }
2. 选择过滤器时自动更新列表
当用户在侧边栏选择过滤器(比如位置、名称)时,调用updateFilterConditions更新筛选条件,filteredData会自动过滤数据:
// 示例:位置过滤器选择事件 function onLocationFilterSelect(selectedLocation) { updateFilterConditions({ location: selectedLocation }) } // 示例:名称过滤器选择事件 function onNameFilterSelect(selectedName) { updateFilterConditions({ name: selectedName }) }
3. 页面渲染筛选后的列表
在模板里直接使用filteredData渲染列表,它会自动响应筛选条件变化:
<template> <!-- 侧边栏过滤器 --> <div class="sidebar"> <select @change="onLocationFilterSelect($event.target.value)"> <!-- 过滤器选项内容 --> </select> </div> <!-- 列表展示区 --> <div class="list-container"> <div v-for="item in filteredData" :key="item.id"> <!-- 渲染每个数据项的内容 --> </div> </div> </template>
你之前拿不到数据的原因
- 重复调用
testStore()创建多个实例,导致数据引用不一致 - 未使用
storeToRefs,Store状态非响应式,数据更新后组件不会重新渲染 - 若Store的
receivedData未初始化空数组,第一次赋值可能无法触发响应式更新
按上述步骤调整后,应该就能解决你的问题啦~
备注:内容来源于stack exchange,提问作者venkat g
相关产品推荐
相关产品推荐

