基于Vant实现一个模糊查询且关键字高亮组件

916 阅读2分钟

简单聊聊

模糊查询功能是提升用户体验的重要组件之一。用户输入关键词后,系统能够快速匹配并展示相关的搜索结果,同时对输入的关键词进行高亮显示,可以让用户更直观地看到匹配项。本文将介绍如何使用Vant框架实现一个模糊查询且关键字高亮的组件。实现效果如下:

20241108110615.png

实现步骤

1、使用vant组件实现布局

这里我就直接使用项目中的代码了,看起来更直观一些

注意:Vant的Overlay组件默认是禁止了蒙层里的内容无法滚动,所以我们需要将这一项配置给关闭 :lock-scroll="false"

  <Overlay :show="show" :lock-scroll="false">
    <Search v-model="stuName" placeholder="请输入学生姓名" autofocus show-action @update:model-value="dbChange">
      <template #left>
        <Icon name="revoke" color="#999" size="20" @click="handleCancel" />
      </template>
      <template #action>
        <div @click="onSave">确定</div>
      </template>
    </Search>
    <div v-show="showSearchBox" class="search-box w-full h-full bg-white overflow-y-auto">
      <template v-if="searchList.length">
        <div class="search-item w-full" v-for="(item, index) in searchList" :key="index" @click="handleChoose(item)">
          <Icon name="search" color="#999eb6" />
          <span class="main-text" v-html="highLightWord(item.name, stuName)" />
        </div>
      </template>
      <Empty v-else description="未查询到人员信息" />
    </div>
  </div>

2、调用接口进行模糊查询

这里我们会用到防抖做输入和接口调用的优化,以及在有内容输入的时候下方内容部分的显示

/**
 * 搜索
 */
const changeValue = async () => {
  if (stuName.value && !showSearchBox.value) {
    showSearchBox.value = true
  }
  if (stuName.value === '') {
    showSearchBox.value = false
  } else {
      /** 这里就是调用接口查询的逻辑 **/
  }
}
/**
 * 防抖处理
 */
const dbChange = debounce(changeValue, 1000)

其实到这里,模糊查询就已经实现了~但是为了用户体验更好,我们来实现一下关键字高亮的效果

3、关键字高亮

思路也很简单,写一个方法过滤每一组字符串,需要高亮的就加高亮的class,过滤器方法返回HTML字符串,通过v-html将返回作为HTML标签解析后输出

过滤方法
/**
 * 文字高亮显示
 * @param text 文字内容
 * @param keyword 关键字
 */
const highLightWord = (text: string, keyword: string) => {
  const reg = new RegExp(keyword, 'g')
  return text.replace(reg, `<span class="txt">${keyword}</span>`)
}
CSS高亮样式
.txt {
  color: orange;
}
HTML中使用
<span class="main-text" v-html="highLightWord(item.name, stuName)" />

到此高亮显示就实现了,注意这里也有一个小坑,就是v-html无法被 style scoped 渲染的问题,也就是上面我们写的css高亮样式,不能写在scoped里面,为什么呢?

原因很简单,scoped的原理是将 template 内所有元素添加一个随机属性(审查元素可以看到,叫做v-data-xxx),然后又把 css 里面的选择器也加上这个属性,保证元素只作用到属性上。但是 v-html 里的元素没有加上这个标签,自然就不会受到影响了。

所以怎么解决呢?一种就是直接取消scoped,不过这样 css 也会影响到全局,另一种就是采用 deep选择器。

希望这篇文章能够帮助你在自己的项目中实现类似的功能。