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

在astro.Build中实现自定义选择器过滤数据并跨页保留选中项

在Astro中实现带状态持久化的JSON数据过滤

核心需求拆解

要解决两个核心问题:一是根据自定义选择器的选项过滤JSON数据,二是页面切换/刷新时保留选中的选项状态。下面提供两种实用方案,可根据场景选择。

方案一:用localStorage持久化选中状态

适合不需要分享状态、仅在用户本地保留选择的场景。

1. 组件实现代码

---
// 导入你的JSON数据文件
import countryData from '../data/your-data.json';
---

<div class="filter-container">
  <select id="countrySelector">
    <option value="">全部国家</option>
    {countryData.map(item => (
      <option key={item.id} value={item.country}>{item.country}</option>
    ))}
  </select>

  <div id="resultsList">
    <!-- 初始渲染全部数据 -->
    {countryData.map(item => (
      <div key={item.id} class="result-item">
        {item.title} - {item.country}
      </div>
    ))}
  </div>
</div>

<script is:inline>
  // 页面加载时读取本地存储的选中状态
  const selector = document.getElementById('countrySelector');
  const savedSelection = localStorage.getItem('selectedCountry');
  if (savedSelection) {
    selector.value = savedSelection;
  }

  // 定义数据过滤与DOM更新函数
  function updateFilteredResults(selectedCountry) {
    const resultsContainer = document.getElementById('resultsList');
    const filtered = selectedCountry 
      ? countryData.filter(item => item.country === selectedCountry)
      : countryData;
    
    resultsContainer.innerHTML = filtered.map(item => `
      <div key="${item.id}" class="result-item">
        ${item.title} - ${item.country}
      </div>
    `).join('');
  }

  // 监听选择器变化,保存状态并更新结果
  selector.addEventListener('change', (e) => {
    const selected = e.target.value;
    localStorage.setItem('selectedCountry', selected);
    updateFilteredResults(selected);
  });

  // 页面初始化时执行一次过滤,确保状态生效
  updateFilteredResults(savedSelection || '');
</script>

2. 关键注意事项

  • 客户端脚本需添加is:inline确保在浏览器端执行;
  • 多页面复用选择器时,每个页面都要加入读取localStorage和过滤的逻辑,保证状态同步;
  • 可通过storage事件监听其他页面的状态变更,实现跨页自动同步。

方案二:用URL参数传递状态

适合需要分享选择状态、或对SEO友好的场景(服务端可预渲染过滤结果)。

1. 组件实现代码

---
import countryData from '../data/your-data.json';
import { getURL } from 'astro:utils';

// 服务端读取URL查询参数,预过滤数据
const currentURL = new URL(getURL());
const selectedCountry = currentURL.searchParams.get('country') || '';
const preFilteredData = selectedCountry 
  ? countryData.filter(item => item.country === selectedCountry)
  : countryData;
---

<div class="filter-container">
  <select id="countrySelector" value={selectedCountry}>
    <option value="">全部国家</option>
    {countryData.map(item => (
      <option key={item.id} value={item.country}>{item.country}</option>
    ))}
  </select>

  <div id="resultsList">
    {preFilteredData.map(item => (
      <div key={item.id} class="result-item">
        {item.title} - {item.country}
      </div>
    ))}
  </div>
</div>

<script is:inline>
  const selector = document.getElementById('countrySelector');

  selector.addEventListener('change', (e) => {
    const selected = e.target.value;
    const url = new URL(window.location.href);
    
    // 更新URL参数
    if (selected) {
      url.searchParams.set('country', selected);
    } else {
      url.searchParams.delete('country');
    }

    // 用pushState更新URL而不刷新页面,同时触发过滤
    window.history.pushState({}, '', url);
    updateFilteredResults(selected);
  });

  function updateFilteredResults(selectedCountry) {
    const resultsContainer = document.getElementById('resultsList');
    const filtered = selectedCountry 
      ? countryData.filter(item => item.country === selectedCountry)
      : countryData;
    
    resultsContainer.innerHTML = filtered.map(item => `
      <div key="${item.id}" class="result-item">
        ${item.title} - ${item.country}
      </div>
    `).join('');
  }
</script>

2. 核心优势

  • 状态通过URL传递,页面切换、刷新或分享链接后都能保留选中状态;
  • 服务端预渲染过滤后的内容,对SEO更友好;
  • 无需依赖本地存储,适合公共场景的状态分享。

通用优化建议

  • 若JSON数据量较大,优先用方案二的服务端预过滤,减少客户端计算压力;
  • 可将过滤逻辑封装成独立的客户端工具函数,在多个页面复用;
  • 选择器样式可自定义,替换为下拉框、单选组等形式,逻辑无需改动。

内容的提问来源于stack exchange,提问作者Davv

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:03:16