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

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>

你之前拿不到数据的原因

  1. 重复调用testStore()创建多个实例,导致数据引用不一致
  2. 未使用storeToRefs,Store状态非响应式,数据更新后组件不会重新渲染
  3. 若Store的receivedData未初始化空数组,第一次赋值可能无法触发响应式更新

按上述步骤调整后,应该就能解决你的问题啦~

备注:内容来源于stack exchange,提问作者venkat g

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 08:43:05