前端搜索的简单实现——精准搜索、模糊搜索、拼音搜索

29,988 阅读3分钟

最近做项目时需要写一个搜索功能,刚开始的时候觉得这功能挺厉害,挺牛逼的,自己做的时候也有点懵逼,上手之后觉得还行,哈哈。下面便是我对搜索这一功能的实现。希望对像我这样的小白有帮助。

精准搜索

**核心思想:**将用户输入的字符串作为一个整体去与数组的每一项做匹配,把符合的保存下来即可。
我们先看一下效果图 这里主要用到的JavaScript字符串的indexOf()方法——返回某个指定的字符串值在字符串中首次出现的位置,如果不存在,则返回-1。

有一点需要注意,`indexOf()` 方法对大小写敏感! 另外数组也有一个`indexOf()`方法

下面是上述实例的完整代码,当然实际开发的时候数据肯定没这么简单。我们这里使用的是Vue + Element

实现

<template>
  <div class="wrapper">
    <el-input
      clearable
      placeholder="请输入"
      suffix-icon="el-icon-search"
      v-model="searchMsg"
      size="mini"
      @input="handleSearch(searchMsg)"
    ></el-input>
    <el-checkbox-group v-model="checkList">
      <div v-for="(item, index) in filterMsg" :key="index">
        <el-checkbox :label="item">{{ item.name }}</el-checkbox>
      </div>
    </el-checkbox-group>
  </div>
</template>
<script>
export default {
  data() {
    return {
      searchMsg: "",
      checkList: [],
      filterMsg: []
    };
  },
  mounted() {
    this.allMsg = [
      { name: "myhua", id: 1 },
      { name: "mp3", id: 2 },
      { name: "hello", id: 3 },
      { name: "world", id: 4 },
      { name: "warm weather", id: 5 },
      { name: "m3", id: 6 },
      { name: "hahaha", id: 7 }
    ];
    this.filterMsg = this.allMsg;
  },
  methods: {
    // 搜索方法
    handleSearch(queryString) {
      this.filterMsg = [];
      this.allMsg.map(item => {
        if (item.name.indexOf(queryString) !== -1) {
          this.filterMsg.push(item);
        }
      });
    }
  }
};
</script>

另外字符串的search()方法在这里也能实现相同的效果,对大小写敏感
在这里推荐使用includes,这样更语义化一些,自己有点懒这里就没改

模糊搜索

**核心思想:**将用户输入的字符串进行拆分去与数组的每一项做匹配,把符合的保存下来即可。要进行拆分这里就需要用到正则表达式
效果图:

实现

// 其余代码同上
handleSearch(queryString) {
  let queryStringArr = queryString.split("");
  let str = "(.*?)";
  this.filterMsg = [];
  let regStr = str + queryStringArr.join(str) + str;
  let reg = RegExp(regStr, "i"); // 以mh为例生成的正则表达式为/(.*?)m(.*?)h(.*?)/i
  this.allMsg.map(item => {
    if (reg.test(item.name)) {
      this.filterMsg.push(item);
    }
  });
}

拼音搜索

核心思想:先获取的汉字的拼音,然后对其进行匹配
获取汉字的拼音我这里使用的是pinyin
简单介说一下pinyin包的用法

import py from "pinyin";
py("中心"); // [ [ 'zhōng' ], [ 'xīn' ] ]  默认是带声调的
py("中心", {
  heteronym: true               // 配置一些设置项,启用多音字模式
});                            // [ [ 'zhōng', 'zhòng' ], [ 'xīn' ] ]

如果你有兴趣想了解一下汉字转拼音的话,可以看一下这篇文章JavaScript 之 300 行代码搞定汉字转拼音,不过这篇文章所写的包为能解决多音字的问题
效果图: 拼音搜索

实现

// 其余代码同上
import py from "pinyin";
mounted() {
    this.allMsg = [
      { name: "薛之谦", id: 1 },
      { name: "霍建华", id: 2 },
      { name: "蔡徐坤", id: 3 },
      { name: "胡歌", id: 4 },
      { name: "胡说", id: 5 }
    ];
    this.filterMsg = this.allMsg;
  },
methods: {
  handleSearch(queryString) {
    let queryStringArr = queryString.split("");
    let str = "(.*?)";
    let regStr = str + queryStringArr.join(str) + str;
    let reg = RegExp(regStr, "i");
    this.filterMsg = [];
    console.log(reg);
    this.allMsg.map(item => {
      // 获取汉字的拼音,并进行扁平化
      let pyArr = py(item.name, {
        style: py.STYLE_NORMAL // 设置拼音风格设置为普通风格(不带声调),
      }).flat();
      let pyStr = pyArr.join("");
      if (reg.test(pyStr)) {
        this.filterMsg.push(item);
      }
    });
  }
}

最后

不同的场景各自的需求都不一样,有可能你会用到上面的一种,也有可能你需要将上面提到的三种方式整合起来形成一个综合搜索。
另外——按更优的体验来讲,我们应该对搜索到的结果根据需求进行排序,对关键字进行高亮展示。这里我就不给大家展示了😁
至于这以上三种方式的性能嘛,我自己感觉还不错,用着还行。希望有经验的大佬能够指点一二