首字母模糊匹配

我们在日常开发中经常会用到筛选的功能,比如一个表格数据,需要根据其中的某一列去进行模糊匹配筛选,一般都是去判断字符串中是否包含某个子字符串,但是这样是不支持首字母模糊匹配的,所以我们可以使用一个第三方包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>
相关推荐
CC码码3 分钟前
告别杂乱数字:用 Intl.NumberFormat 打造全球友好的前端体验
前端·javascript·面试
妮妮喔妮13 分钟前
Webpack和Vite优化的区别
前端·webpack·node.js
广州华水科技33 分钟前
单北斗GNSS在大坝形变监测中的应用与性能分析
前端
等风来不如迎风去39 分钟前
【web】页面透明、插入图片
前端
谢尔登42 分钟前
a 标签的跳转机制
前端·javascript·webpack·node.js
狂炫冰美式1 小时前
当硅基神明撞上人类的“叹息之墙”:距离证明哥德巴赫猜想,AI还有多远?
前端·算法·架构
毕设源码-邱学长1 小时前
【开题答辩全过程】以 基于Vue的爱心公益募捐平台的设计与实现为例,包含答辩的问题和答案
前端·javascript·vue.js
IT_陈寒1 小时前
Redis实战精要:5种高频使用场景与性能优化全解析|得物技术
前端·人工智能·后端
Hilaku2 小时前
那个把代码写得亲妈都不认的同事,最后被劝退了🤷‍♂️
前端·javascript·代码规范
南囝coding2 小时前
Node.js 原生功能狂飙,15 个热门 npm 包要失业了
前端·后端