简介
pinyin-match 是一个轻量级的 JavaScript 拼音匹配库,支持中文拼音搜索和匹配。它可以将中文文本转换为拼音,并支持模糊匹配,特别适用于搜索功能、自动补全、数据过滤等场景。
主要特性
- 🚀 轻量级: 压缩后仅约 20KB
- 🎯 高性能: 基于优化的算法,快速匹配
- 📝 中文支持: 完整的中文拼音转换
- 🔍 模糊匹配: 支持拼音首字母、全拼、模糊匹配
- 🌐 多音字支持: 智能处理多音字
- 🔧 简单易用: 简洁的 API 设计
安装
# npm
npm install pinyin-match
# yarn
yarn add pinyin-match
# pnpm
pnpm add pinyin-match
基础用法
基本匹配
import pinyinMatch from "pinyin-match";
// 基础匹配
const result = pinyinMatch.match("你好世界", "nihao");
console.log(result); // true
// 首字母匹配
const result2 = pinyinMatch.match("你好世界", "nhsj");
console.log(result2); // true
// 混合匹配
const result3 = pinyinMatch.match("你好世界", "ni世界");
console.log(result3); // true
数组过滤
import pinyinMatch from "pinyin-match";
const data = [
{ name: "张三", age: 25 },
{ name: "李四", age: 30 },
{ name: "王五", age: 28 },
{ name: "赵六", age: 35 },
];
// 根据姓名拼音过滤
const filtered = data.filter((item) => pinyinMatch.match(item.name, "zhang"));
console.log(filtered); // [{ name: '张三', age: 25 }]
// 多条件匹配
const filtered2 = data.filter(
(item) =>
pinyinMatch.match(item.name, "li") || pinyinMatch.match(item.name, "李")
);
console.log(filtered2); // [{ name: '李四', age: 30 }]
获取匹配位置
import pinyinMatch from "pinyin-match";
// 获取匹配的详细信息
const result = pinyinMatch.match("你好世界", "ni", {
returnMatchIndex: true,
});
console.log(result);
// {
// matched: true,
// index: 0,
// length: 2
// }
高级功能
自定义匹配选项
import pinyinMatch from "pinyin-match";
const options = {
// 是否忽略大小写
caseSensitive: false,
// 是否返回匹配位置
returnMatchIndex: true,
// 是否支持模糊匹配
fuzzy: true,
};
const result = pinyinMatch.match("你好世界", "nhsj", options);
console.log(result);
批量处理
import pinyinMatch from "pinyin-match";
const cities = [
"北京",
"上海",
"广州",
"深圳",
"杭州",
"南京",
"武汉",
"成都",
"西安",
"重庆",
];
// 批量搜索
function searchCities(keyword) {
return cities.filter((city) => pinyinMatch.match(city, keyword));
}
console.log(searchCities("beijing")); // ['北京']
console.log(searchCities("sh")); // ['上海', '深圳']
console.log(searchCities("bj")); // ['北京']
多音字处理
import pinyinMatch from "pinyin-match";
// 多音字自动处理
const result1 = pinyinMatch.match("重庆", "chongqing");
console.log(result1); // true
const result2 = pinyinMatch.match("重庆", "zhongqing");
console.log(result2); // true
const result3 = pinyinMatch.match("重庆", "cq");
console.log(result3); // true
实际应用场景
搜索组件
<template>
<div class="search-container">
<input
v-model="keyword"
placeholder="请输入搜索关键词..."
class="search-input"
/>
<div class="search-results">
<div v-for="item in filteredData" :key="item.id" class="result-item">
{{ item.name }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
import pinyinMatch from "pinyin-match";
const keyword = ref("");
const data = ref([
{ id: 1, name: "张三" },
{ id: 2, name: "李四" },
{ id: 3, name: "王五" },
{ id: 4, name: "赵六" },
{ id: 5, name: "孙七" },
]);
const filteredData = computed(() => {
if (!keyword.value) return data.value;
return data.value.filter((item) =>
pinyinMatch.match(item.name, keyword.value)
);
});
</script>
自动补全组件
<template>
<div class="autocomplete-container">
<input
v-model="inputValue"
@input="handleInput"
@focus="showDropdown = true"
@blur="handleBlur"
placeholder="请输入姓名..."
class="autocomplete-input"
/>
<div v-if="showDropdown && suggestions.length > 0" class="dropdown">
<div
v-for="suggestion in suggestions"
:key="suggestion.id"
@click="selectSuggestion(suggestion)"
class="suggestion-item"
>
<span v-html="highlightMatch(suggestion.name, inputValue)"></span>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
import pinyinMatch from "pinyin-match";
const inputValue = ref("");
const showDropdown = ref(false);
const data = ref([
{ id: 1, name: "张三" },
{ id: 2, name: "李四" },
{ id: 3, name: "王五" },
{ id: 4, name: "赵六" },
{ id: 5, name: "孙七" },
]);
const suggestions = computed(() => {
if (!inputValue.value) return [];
return data.value
.filter((item) => pinyinMatch.match(item.name, inputValue.value))
.slice(0, 5); // 限制显示数量
});
const handleInput = () => {
showDropdown.value = true;
};
const handleBlur = () => {
setTimeout(() => {
showDropdown.value = false;
}, 200);
};
const selectSuggestion = (suggestion) => {
inputValue.value = suggestion.name;
showDropdown.value = false;
};
const highlightMatch = (text, keyword) => {
// 简单的匹配高亮实现
if (!keyword) return text;
const regex = new RegExp(`(${keyword})`, "gi");
return text.replace(regex, "<mark>$1</mark>");
};
</script>
树形结构搜索
import pinyinMatch from "pinyin-match";
// 递归搜索树形结构
function searchTree(nodes, keyword) {
const results = [];
function traverse(node) {
// 检查当前节点是否匹配
if (pinyinMatch.match(node.name, keyword)) {
results.push(node);
}
// 递归搜索子节点
if (node.children && node.children.length > 0) {
node.children.forEach((child) => traverse(child));
}
}
nodes.forEach((node) => traverse(node));
return results;
}
// 使用示例
const treeData = [
{
id: 1,
name: "技术部",
children: [
{ id: 11, name: "前端组", children: [] },
{ id: 12, name: "后端组", children: [] },
],
},
{
id: 2,
name: "产品部",
children: [
{ id: 21, name: "产品设计组", children: [] },
{ id: 22, name: "用户体验组", children: [] },
],
},
];
const searchResults = searchTree(treeData, "jishu");
console.log(searchResults); // [{ id: 1, name: '技术部', children: [...] }]
常见问题
多音字处理
问题: 某些多音字匹配不准确
解决方案:
// 自定义多音字映射
const customPinyinMap = {
重: ["zhong", "chong"],
长: ["chang", "zhang"],
};
// 扩展匹配函数
function customMatch(text, keyword) {
// 先尝试标准匹配
if (pinyinMatch.match(text, keyword)) return true;
// 再尝试自定义映射
for (const [char, pinyins] of Object.entries(customPinyinMap)) {
if (text.includes(char)) {
for (const pinyin of pinyins) {
if (pinyinMatch.match(text.replace(char, pinyin), keyword)) {
return true;
}
}
}
}
return false;
}
特殊字符处理
问题: 包含特殊字符的文本匹配失败
解决方案:
// 预处理文本
function preprocessText(text) {
return text
.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, "") // 移除特殊字符
.trim();
}
// 使用预处理后的文本进行匹配
const result = pinyinMatch.match(preprocessText("你好,世界!"), "nihao");
总结
pinyin-match 是一个功能强大且易用的中文拼音匹配库,特别适合需要中文搜索功能的项目。通过合理使用其 API 和优化策略,可以构建出高性能的中文搜索体验。
原文链接:https://code.ifrontend.net/archives/1005,转载请注明出处。
评论0