这篇文章主要介绍“JS怎么实现拼音匹配汉字”,在日常操作中,相信很多人在JS怎么实现拼音匹配汉字问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS怎么实现拼音匹配汉字”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
1. 首先说下功能
它能够使用拼音快速检索目标。当然也可以使用汉字
简体版27KB (gzip ≈ 19KB),繁体版86KB (gzip ≈ 60KB)
支持多音字、繁体字、拼音首字母匹配,具备分词功能
返回位置信息,可用于高亮匹配字符
在长多音字串下依然有高性能
2. 安装
npm install pinyin-match --save
3. 引入
简体版:
import PinyinMatch from 'pinyin-match'; // es const PinyinMatch = require('pinyin-match'); // commonjs
繁体版:
import PinyinMatch from 'pinyin-match/es/traditional.js'; // es const PinyinMatch = require('pinyin-match/lib/traditional.js'); // commonjs
当然也可以script引入
// 简体: <script src="pinyin-match/dist/main.js"></script> // 繁体: <script src="pinyin-match/dist/traditional.js"></script>
4. API
.match(input, keyword) //查询匹配拼音的数据。
只向外提供暴露了这么一个方法,这一个方法足够我们使用了,也很方便
参数:
input {string} 目标字符串
keyword {string} 输入的拼音或其他关键词
返回:
Array | Boolen
5. 简单使用测试示例
let test = '123曾经沧海难为水除却巫山不是云' PinyinMatch.match(test, '23曾'); // [1, 3] PinyinMatch.match(test, 'cjc') // [3, 5] PinyinMatch.match(test, 'cengjingcanghai') // [3, 6] PinyinMatch.match(test, 'cengjingcangha') // [3, 6] PinyinMatch.match(test, 'engjingcanghai') // false PinyinMatch.match(test, 'zengjingcang') // [3, 5] PinyinMatch.match(test, 'sdjkelwqf') // false PinyinMatch.match(test, 'zengji ng cang') // [3, 5] PinyinMatch.match(test, 'zengji ng cangsdjfkl') // false PinyinMatch.match(' 我 爱你 中 国 ', 'nzg') // [6, 12] PinyinMatch.match(' 我 爱你 中 国 ', '爱你中') // [5, 8] PinyinMatch.match('發', 'fa') // [0, 0]
6. 具体案例
就是平常的列表展示加模糊搜索。所用的人员列表测试数据都是下面这种格式,章末会把完整测试数据附上。
// 模拟后端返回的数据 export default [ { name: '管理员', no: 'FT00000' }, //... ]
其实很简单的了,主要是实现拼音的搜索过滤的功能,所以我案例里面样式也没调,主要是功能
闲话不说了,直接上完整代码,大家看下里面的逻辑都明白了,就这么一个组件:
<template> <div class="main"> <input type="text" v-model="serchValue" placeholder="输入搜索"> <div class="user" v-for="(user, index) in users" :key="user.no">{{ index }}# : {{ user.name }}</div> </div> </template> <script> import userList from './data/user' import PinyinMatch from 'pinyin-match' let timer = null export default { data() { return { serchValue: '', userListAll: [], // 所有数据 users: [] // 展示的数据 } }, watch: { serchValue() { this.debounce(this.selectUser, 200) } }, mounted(){ this.getUserList() }, methods:{ // 模拟请求 getUserList() { setTimeout(() => { this.userListAll = userList this.selectUser() }, 100) }, // 防抖 debounce(fn, wait) { if(timer) clearTimeout(timer) timer = setTimeout(() => { fn.call(this) timer = null }, wait) }, // 模糊查询条件 selectUser() { this.users = [] // 如果搜索框有值的话再去过滤,因为PinyinMatch.match第二个参数是空字符串的话会匹配不到,返回false,这不符合我们的预期 // 搜索框没有值,我们要展示所有数据 if(this.serchValue) { this.userListAll.forEach(user => { let matchIndexs = PinyinMatch.match(user.name, this.serchValue) // 如果匹配到返回 首尾的索引数组,如果匹配不到则返回false if(matchIndexs) { this.users.push(user) } }) } else { this.users = this.userListAll } } } } </script> <style scoped> .main { width: 100vw; height: 100vh; padding: 200px 0 0 200px; box-sizing: border-box; } .main input { margin-bottom: 5px; } </style>
接下来看下效果:
接下来!我们可以把上面的示例再提高点儿难度,因为让我想起了通讯录,所以在展示的时候我们就像通讯录那样展示
首先将拿到的人员列表进行分组,根据什么分呢?就是根据字母,a、b、c...这样,难道我们要把26个英文字母全都列出来吗?当然这个也分需求,但如果是通讯录的话,我们只需要百家姓中所有的拼音的首字母就可以了,也就是:abcdefghjklmnopqrstwxyz 这些。
在上面示例的基础上进行修改,在拿到人员数据之后,先处理一下,然后再进行过滤模糊查询
完整代码:
<template> <div class="main"> <input type="text" v-model="serchValue" placeholder="输入搜索"> <div class="users" v-for="user in users" :key="user.key"> <div>{{ user.key }}</div> <div class="user-name" v-for="o in user.data" :key="o.no">{{ o.name }}</div> </div> </div> </template> <script> import userList from './data/user' import PinyinMatch from 'pinyin-match' let timer = null export default { data() { return { serchValue: '', userListAll: [], // 所有数据 users: [] // 展示的数据 } }, watch: { serchValue() { this.debounce(this.selectUser, 200) } }, mounted(){ this.getUserList() }, methods:{ // 模拟请求 getUserList() { setTimeout(() => { this.userListAll = this.handlerData(userList) this.selectUser() }, 100) }, // 处理数据 handlerData(userList) { // 这是百家姓中所有的拼音的首字母 const surnameLetters = 'abcdefghjklmnopqrstwxyz'.split('') const userListAll = [] surnameLetters.forEach(letter => { let o = { key: letter, data: [] } userList.forEach(user => { let matchIndexs = PinyinMatch.match(user.name.slice(0, 1), letter) // 匹配姓氏的拼音的首字母 if(matchIndexs) { o.data.push(user) } }) if(o.data.length) { userListAll.push(o) } }) return userListAll }, // 防抖 debounce(fn, wait) { if(timer) clearTimeout(timer) timer = setTimeout(() => { fn.call(this) timer = null }, wait) }, // 模糊查询条件 selectUser() { this.users = [] if(this.serchValue) { this.userListAll.forEach(user => { let o = { key: user.key, data: [] } user.data.forEach(item => { let matchIndexs = PinyinMatch.match(item.name, this.serchValue) if(matchIndexs) { o.data.push(item) } }) if(o.data.length) { this.users.push(o) } }) } else { this.users = this.userListAll } } } } </script> <style scoped> .main { width: 100%; height: 100%; padding: 0 0 0 200px; box-sizing: border-box; } .main input { margin-bottom: 5px; } .user-name { padding-left: 10px; } </style>
最后看下修改后的效果:
接下来是上面测试用的数据
export default [ { "name": "管理员", "no": "FT00000" }, { "name": "朱大锤", "no": "FT00001" }, { "name": "郝大锤", "no": "FT00002" }, { "name": "宋大锤", "no": "FT00003" }, { "name": "杨大锤", "no": "FT00004" }, { "name": "石大锤", "no": "FT00005" }, { "name": "郑大锤", "no": "FT00006" }, { "name": "刘大锤", "no": "FT00007" }, { "name": "赵大锤", "no": "FT00008" }, { "name": "李大锤", "no": "FT00009" }, { "name": "牛二", "no": "FT00010" }, { "name": "张大锤", "no": "FT00011" }, { "name": "王大锤", "no": "FT00012" }, { "name": "冯大锤", "no": "FT00013" }, { "name": "李大锤", "no": "FT00014" }, { "name": "邓大锤", "no": "FT00015" }, { "name": "孙大锤", "no": "FT00016" }, { "name": "袁大锤", "no": "FT00017" }, { "name": "康大锤", "no": "FT00018" }, { "name": "武大锤", "no": "FT00019" }, { "name": "蔡大锤", "no": "FT00020" }, { "name": "戴大锤", "no": "FT00021" }, { "name": "鄂大锤", "no": "FT00022" }, { "name": "封大锤", "no": "FT00023" }, { "name": "盖大锤", "no": "FT00024" }, { "name": "景大锤", "no": "FT00025" }, { "name": "麻大锤", "no": "FT00026" }, { "name": "那大锤", "no": "FT00027" } ]