JavaScript 前端原创内容搜索:Vue3+Pinia 实现本地检索与高亮匹配
·
以下是一个原创的、结构清晰的解决方案,使用 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.map和Array.filter处理数据。highlightMatch函数通过正则表达式匹配关键词,并添加 HTML 标签。 - 高亮原理:通过 CSS 类
.highlight实现视觉高亮。HighlightText组件安全渲染 HTML(确保数据来源可信)。 - 性能优化:搜索在客户端完成,避免不必要的网络请求;使用 Pinia 的响应式状态,确保 UI 自动更新。
- 安全注意:
v-html渲染时需防范 XSS 攻击(本方案假设数据可信)。如果数据来自用户输入,建议使用 DOMPurify 等库清洗。
4. 完整示例流程
- 初始化:在 Vue 应用入口(如
main.js)安装 Pinia。 - 数据加载:在组件中设置
items(可从本地 JSON 或 API 获取)。 - 用户交互:用户在输入框输入时,触发
setSearchQuery,更新结果。 - 渲染:结果列表使用
HighlightText组件显示高亮文本。
5. 总结
- 效果:实现实时本地搜索,关键词高亮突出,提升用户体验。
- 扩展性:可轻松添加更多功能,如分页、多字段搜索(修改
performSearch中的逻辑)。 - 依赖:仅需 Vue3 和 Pinia,无需额外库。
- 测试建议:使用 Jest 测试搜索和高亮逻辑,确保边界情况(如空查询、特殊字符)。
此方案完全原创,基于 Vue3 和 Pinia 的最佳实践。代码简洁,易于集成到现有项目中。如果有具体数据格式或需求变更,可进一步调整搜索函数。
更多推荐
所有评论(0)