以下是一个原创的、结构清晰的解决方案,使用 Vue3 和 Pinia 实现前端本地搜索功能,包括检索逻辑和高亮匹配。整个方案基于 Composition API 设计,确保代码简洁高效。我们将分步骤实现:

1. 概述

  • 目标:在 Vue3 应用中,通过 Pinia 管理状态,实现本地数据(如数组)的实时搜索,并在结果中高亮显示匹配文本。
  • 核心组件
    • Pinia store:存储搜索查询、原始数据和搜索结果。
    • 搜索函数:使用 JavaScript 字符串方法进行本地匹配。
    • 高亮组件:通过自定义 Vue 组件渲染高亮文本。
  • 优势:纯前端实现,无需后端 API,响应快速;Pinia 提供状态共享,便于多组件复用。

2. 实现步骤

步骤 1: 设置 Pinia Store
  • 创建一个 Pinia store 来管理搜索状态。使用 defineStore 定义状态和操作。
  • 状态searchQuery(搜索关键词)、items(原始数据数组)、filteredItems(搜索结果)。
  • 操作setSearchQuery 更新查询,performSearch 执行搜索逻辑。
// 文件:stores/searchStore.js
import { defineStore } from 'pinia';

export const useSearchStore = defineStore('search', {
  state: () => ({
    searchQuery: '', // 搜索关键词
    items: [],       // 原始数据(示例:对象数组)
    filteredItems: [] // 搜索结果
  }),
  actions: {
    // 更新搜索查询并触发搜索
    setSearchQuery(query) {
      this.searchQuery = query;
      this.performSearch();
    },
    // 执行搜索逻辑:过滤并高亮匹配项
    performSearch() {
      if (!this.searchQuery.trim()) {
        this.filteredItems = [...this.items]; // 无查询时显示全部
        return;
      }
      const query = this.searchQuery.toLowerCase();
      this.filteredItems = this.items.map(item => {
        // 检查每个字段是否匹配(示例:假设 item 有 title 和 content)
        const titleMatch = this.highlightMatch(item.title, query);
        const contentMatch = this.highlightMatch(item.content, query);
        return { ...item, title: titleMatch, content: contentMatch }; // 返回带高亮的数据
      }).filter(item => 
        item.title.includes('<span class="highlight">') || // 仅保留有匹配的项
        item.content.includes('<span class="highlight">')
      );
    },
    // 高亮匹配函数:返回带 HTML 标签的字符串
    highlightMatch(text, query) {
      const regex = new RegExp(`(${query})`, 'gi'); // 全局不区分大小写匹配
      return text.replace(regex, '<span class="highlight">$1</span>'); // 包裹匹配文本
    }
  }
});

步骤 2: 创建高亮显示组件
  • 使用 Vue3 的 v-html 渲染带 HTML 的高亮文本,但需注意 XSS 安全(确保数据可信)。
  • 定义 CSS 样式实现高亮效果。
<!-- 文件:components/HighlightText.vue -->
<template>
  <span v-html="content"></span> <!-- 安全渲染 HTML -->
</template>

<script setup>
import { defineProps } from 'vue';

const props = defineProps({
  content: String // 传入带高亮标签的字符串
});
</script>

<style scoped>
.highlight {
  background-color: yellow; /* 高亮样式 */
  font-weight: bold;
}
</style>

步骤 3: 在 Vue 组件中集成搜索
  • 使用 Pinia store 在组件中绑定搜索输入和显示结果。
  • 示例:一个搜索页面组件。
<!-- 文件:views/SearchView.vue -->
<template>
  <div>
    <input 
      type="text" 
      v-model="searchQuery" 
      placeholder="输入关键词搜索" 
      @input="updateQuery"
    />
    <ul v-if="filteredItems.length">
      <li v-for="(item, index) in filteredItems" :key="index">
        <h3><HighlightText :content="item.title" /></h3> <!-- 使用高亮组件 -->
        <p><HighlightText :content="item.content" /></p>
      </li>
    </ul>
    <p v-else>无匹配结果</p>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';
import { useSearchStore } from '@/stores/searchStore';
import HighlightText from '@/components/HighlightText.vue';

const store = useSearchStore();
const searchQuery = ref('');

// 初始化数据(示例:从 API 或本地加载)
store.items = [
  { id: 1, title: 'Vue3 教程', content: '学习 Vue3 的 Composition API' },
  { id: 2, title: 'Pinia 指南', content: 'Pinia 是 Vue 的状态管理库' }
];

// 监听输入变化,更新 store
const updateQuery = () => {
  store.setSearchQuery(searchQuery.value);
};

// 初始加载数据
store.performSearch();
const filteredItems = ref(store.filteredItems);
watch(() => store.filteredItems, (newVal) => {
  filteredItems.value = newVal;
});
</script>

3. 关键逻辑说明

  • 搜索机制:在 Pinia store 中,performSearch 方法使用 Array.mapArray.filter 处理数据。highlightMatch 函数通过正则表达式匹配关键词,并添加 HTML 标签。
  • 高亮原理:通过 CSS 类 .highlight 实现视觉高亮。HighlightText 组件安全渲染 HTML(确保数据来源可信)。
  • 性能优化:搜索在客户端完成,避免不必要的网络请求;使用 Pinia 的响应式状态,确保 UI 自动更新。
  • 安全注意v-html 渲染时需防范 XSS 攻击(本方案假设数据可信)。如果数据来自用户输入,建议使用 DOMPurify 等库清洗。

4. 完整示例流程

  1. 初始化:在 Vue 应用入口(如 main.js)安装 Pinia。
  2. 数据加载:在组件中设置 items(可从本地 JSON 或 API 获取)。
  3. 用户交互:用户在输入框输入时,触发 setSearchQuery,更新结果。
  4. 渲染:结果列表使用 HighlightText 组件显示高亮文本。

5. 总结

  • 效果:实现实时本地搜索,关键词高亮突出,提升用户体验。
  • 扩展性:可轻松添加更多功能,如分页、多字段搜索(修改 performSearch 中的逻辑)。
  • 依赖:仅需 Vue3 和 Pinia,无需额外库。
  • 测试建议:使用 Jest 测试搜索和高亮逻辑,确保边界情况(如空查询、特殊字符)。

此方案完全原创,基于 Vue3 和 Pinia 的最佳实践。代码简洁,易于集成到现有项目中。如果有具体数据格式或需求变更,可进一步调整搜索函数。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐