首字母模糊匹配

我们在日常开发中经常会用到筛选的功能,比如一个表格数据,需要根据其中的某一列去进行模糊匹配筛选,一般都是去判断字符串中是否包含某个子字符串,但是这样是不支持首字母模糊匹配的,所以我们可以使用一个第三方包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>
相关推荐
Hexene...2 分钟前
【前端Vue】npm install时根据新的状态重新引入实际用到的包,不引入未使用到的
前端·vue.js·npm
2301_780669868 分钟前
Vue(入门配置、常用指令)、Ajax、Axios
前端·vue.js·ajax·javaweb
码农幻想梦8 分钟前
Vue3入门到实战【尚硅谷】
前端·vue
hudou_k10 分钟前
利用WebNaket实现Web应用直接访问硬件设备
前端
吃茄子的猫10 分钟前
若依框架根据当前登录人信息,显示不同的静态公司logo
前端·vue
LZQ <=小氣鬼=>19 分钟前
React + Ant Design (antd) 国际化完整实战教程
前端·react.js·前端框架·antd·moment
星海拾遗22 分钟前
react源码从入门到入定
前端·javascript·react.js
Charlie_lll25 分钟前
学习Three.js–星环粒子(ShaderMaterial)
前端·three.js
wuhen_n30 分钟前
JavaScript事件循环(下) - requestAnimationFrame与Web Workers
开发语言·前端·javascript
我是ed.32 分钟前
Vue3 音频标注插件 wavesurfer
前端·vue.js·音视频