首字母模糊匹配

我们在日常开发中经常会用到筛选的功能,比如一个表格数据,需要根据其中的某一列去进行模糊匹配筛选,一般都是去判断字符串中是否包含某个子字符串,但是这样是不支持首字母模糊匹配的,所以我们可以使用一个第三方包pinyin去实现这种功能。

pinyin可以直接使用npm下载。

1.表格的筛选

js 复制代码
export function searchedFilter(rows, searchValue, keyValue) {
  searchValue = searchValue.trim();
  if (searchValue) {
    const pathen = /^[\u4e00-\u9fa5]+$/;
    if (pathen.test(searchValue)) {
      return rows.filter((data) => {
        return Object.keys(data).some((key) => {
          if (key === keyValue) {
            return data[key].includes(searchValue);
          }
        });
      });
    } else {
      const searchValuePinyin = pinyin(searchValue, {
        style: pinyin.STYLE_FIRST_LETTER,
      }).join("");
      return rows.filter((data) => {
        return Object.keys(data).some((key) => {
          if (key === keyValue) {
            const dataPyArr = pinyin(data[key], {
              style: pinyin.STYLE_FIRST_LETTER,
            });
            const dataPy = dataPyArr.join("");
            return dataPy.includes(searchValuePinyin);
          }
        });
      });
    }
  }
  return rows;
}

该方法接收三个参数,rows是表格数据,searchValue是筛选字符串,keyValue是要匹配的表格的某一列的prop

下面举个例子:

html 复制代码
<template>
  <div class="screen-view">
    <span>筛选字段:</span>
    <el-input v-model="filterText" style="width:120px"></el-input>
    <el-button @click="filterHandle" type="primary">筛选</el-button>
    <el-table :data="showTableData" stripe border height="500" :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }">
      <el-table-column label="姓名" prop="name"></el-table-column>
      <el-table-column label="地址" prop="address"></el-table-column>
      <el-table-column label="职位" prop="job"></el-table-column>
    </el-table>
  </div>
</template>

<script>
import { searchedFilter } from '@/utils/changePinyin'
export default {
  data() {
    return {
      tableData: [
        { name: '月亮', address: '江苏省南京市', job: '前端开发' },
        { name: '月亮1', address: '江苏省南京市', job: '前端开发' },
        { name: '月亮2', address: '江苏省南京市', job: '前端开发' },
        { name: '大傻', address: '安徽省合肥市', job: '后端开发' },
        { name: '大傻1', address: '安徽省合肥市', job: '后端开发' },
        { name: '大傻2', address: '安徽省合肥市', job: '后端开发' },
        { name: '二狗', address: '四川省成都市', job: '前端开发' },
        { name: '二狗1', address: '四川省成都市', job: '前端开发' },
        { name: '二狗2', address: '四川省成都市', job: '前端开发' },
        { name: '三驴子', address: '河南省郑州市', job: '后端开发' },
        { name: '三驴子1', address: '河南省郑州市', job: '后端开发' },
        { name: '三驴子2', address: '河南省郑州市', job: '后端开发' },
      ],
      showTableData: [],
      filterText: ''
    }
  },
  created() {
    this.showTableData = this.tableData
  },
  methods: {
    filterHandle() {
      this.showTableData = searchedFilter(this.tableData, this.filterText, 'name')
      // 这就是筛选表格的姓名字段,如果想筛选别的就把name换成对应的prop
      // 支持首字母匹配
    }
  }
}
</script>

<style lang="scss" scoped>
.screen-view {
  height: 100%;
  padding: 10px;
  box-sizing: border-box;
}
</style>

这个方法只能根据表格的一列进行筛选,如果想同时匹配多列的话,可以使用下面的方法。

js 复制代码
export function searchedFilters(rows, searchValue, keyValues) {
  searchValue = searchValue.trim();
  if (searchValue) {
    const pathen = /^[\u4e00-\u9fa5]+$/;
    if (pathen.test(searchValue)) {
      return rows.filter((data) => {
        return Object.keys(data).some((key) => {
          return keyValues.some((k) => {
            if (key === k) {
              return data[key].includes(searchValue);
            }
          });
        });
      });
    } else {
      const searchValuePinyin = pinyin(searchValue, {
        style: pinyin.STYLE_FIRST_LETTER,
      }).join("");
      return rows.filter((data) => {
        return Object.keys(data).some((key) => {
          return keyValues.some((k) => {
            if (key === k) {
              const dataPyArr = pinyin(data[key], {
                style: pinyin.STYLE_FIRST_LETTER,
              });
              const dataPy = dataPyArr.join("");
              return dataPy.includes(searchValuePinyin);
            }
          });
        });
      });
    }
  }
  return rows;
}

还是接收三个参数,前面两个跟第一个方法一样,表格数据和筛选字符串,第三个是一个数组,里面存放的是你想匹配的列。

比如我们想同时筛选姓名和地址这两列:

js 复制代码
    filterHandle() {
      this.showTableData = searchedFilters(this.tableData, this.filterText, ['name', 'address'])
    }

2.树结构的筛选

js 复制代码
export function treeFilterPY(data, searchValue, keyValue) {
  searchValue = searchValue.trim();
  if (!searchValue) return true;
  const pathen = /^[\u4e00-\u9fa5]+$/;
  if (pathen.test(searchValue)) {
    return data[keyValue].indexOf(searchValue) !== -1;
  }
  // 匹配小写
  const labelValue = pinyin(data[keyValue], {
    style: pinyin.STYLE_FIRST_LETTER,
  }).join("");
  const searchValuePinyin = pinyin(searchValue, {
    style: pinyin.STYLE_FIRST_LETTER,
  }).join("");
  return labelValue.indexOf(searchValuePinyin) !== -1;
}

这个方法接收三个参数,分别是树结构数据,筛选字符串,对应的prop。

html 复制代码
<template>
  <div class="screen-view">
    <span>筛选字段:</span>
    <el-input v-model="filterText" style="width:120px"></el-input>
    <el-button @click="filterHandle" type="primary">筛选</el-button>
    <el-tree ref="treeRef" :data="treeData" :filter-node-method="filterNode"></el-tree>
  </div>
</template>

<script>
import { treeFilterPY } from '@/utils/changePinyin'
export default {
  data() {
    return {
      defaultProps: {
        children: "children",
        label: "label",
      },
      treeData: [
        {
          label: '全部',
          id: -1,
          children: [
            {
              label: '月亮',
              id: 1
            },
            {
              label: '大傻',
              id: 2
            },
            {
              label: '二狗',
              id: 3
            },
            {
              label: '三驴子',
              id: 4
            },
          ]
        }
      ],
      filterText: ''
    }
  },
  created() {
    this.showTableData = this.tableData
  },
  methods: {
    filterHandle() {
      this.$refs.treeRef.filter(this.filterText);
    },
    filterNode(value, data) {
      return treeFilterPY(data, value, this.defaultProps.label);
    },
  }
}
</script>

<style lang="scss" scoped>
.screen-view {
  height: 100%;
  padding: 10px;
  box-sizing: border-box;
}
</style>
相关推荐
一 乐6 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
C_心欲无痕7 小时前
ts - tsconfig.json配置讲解
linux·前端·ubuntu·typescript·json
清沫7 小时前
Claude Skills:Agent 能力扩展的新范式
前端·ai编程
yinuo7 小时前
前端跨页面通信终极指南:方案拆解、对比分析
前端
yinuo8 小时前
前端跨页面通讯终极指南⑨:IndexedDB 用法全解析
前端
xkxnq8 小时前
第二阶段:Vue 组件化开发(第 16天)
前端·javascript·vue.js
烛阴9 小时前
拒绝配置地狱!5 分钟搭建 Three.js + Parcel 完美开发环境
前端·webgl·three.js
xkxnq9 小时前
第一阶段:Vue 基础入门(第 15天)
前端·javascript·vue.js
anyup10 小时前
2026第一站:分享我在高德大赛现场学到的技术、产品与心得
前端·架构·harmonyos
BBBBBAAAAAi10 小时前
Claude Code安装记录
开发语言·前端·javascript