Vue + Element UI 实现模糊搜索自动补全


前言

本文将以 Vue 2.x + Element UI 技术栈为基础,结合实际业务需求,详细讲解如何构建一个支持以下功能的自动补全组件:

  • 高性能模糊匹配
  • 智能时间推荐(单月/区间)
  • 动态组合模板与页面类型适配
  • 支持海量数据快速响应

一、需求分析

📌 业务场景

每个页面都有不同的提问格式要求:

  • monitor 页面:{用户} + {月度日期} + {具体问题}
    示例:广州 2024年7月 售卖情况
  • event / reason 页面:{月度日期} + {用户} + {具体问题}
    示例:2024年7月 广州 特殊事件

二、技术实现

✅ 技术选型

  • 框架:Vue 2.x
  • UI库:Element UI
  • 核心组件:el-autocomplete
  • 数据结构:动态模板 + 正则解析 + 缓存优化

2.1 基础结构 ------ 使用 el-autocomplete

vue 复制代码
<template>
  <el-autocomplete
    v-model="searchQuery"
    :fetch-suggestions="querySearchAsync"
    placeholder="请输入关键词进行搜索"
    @select="handleSelect"
  >
    <!-- 自定义下拉项显示 -->
    <template slot-scope="{ item }">
      <el-tooltip class="item" effect="dark" :content="item.value" placement="top">
        <div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 300px;">
          {{ item.value }}
        </div>
      </el-tooltip>
    </template>
  </el-autocomplete>
</template>

2.2 智能时间推荐与区间解析

🎯 需求目标

  • 输入"2024年7月" → 补全为"2024年7月"
  • 输入"7月" → 补全为"2024年7月"
  • 输入"1-7月" → 补全为"2024年1-7月"
  • "累计售电量情况"只推荐区间时间

🧠 实现思路

通过正则表达式提取用户输入中的时间信息,并根据当前年份进行补全。

js 复制代码
function parseMonthFromQuery(query, isRange = false) {
  const now = new Date();
  const year = now.getFullYear();
  const month = now.getMonth() + 1;

  if (isRange) {
    // 匹配完整区间格式:2024年1-7月
    const rangeFull = query.match(/(20\d{2})年(\d{1,2})-(\d{1,2})月/);
    if (rangeFull) return [`${rangeFull[1]}年${rangeFull[2]}-${rangeFull[3]}月`];

    // 匹配简写区间格式:1-7月
    const rangeMonth = query.match(/(\d{1,2})-(\d{1,2})月/);
    if (rangeMonth) return [`${year}年${rangeMonth[1]}-${rangeMonth[2]}月`];

    // 只输入年份
    const yearMatch = query.match(/(20\d{2})/);
    if (yearMatch) return [`${yearMatch[1]}年1-${month}月`];

    // 只输入月份
    const monthMatch = query.match(/(\d{1,2})月/);
    if (monthMatch) return [`${year}年1-${parseInt(monthMatch[1], 10)}月`];

    // 默认:今年1-当前月
    return [`${year}年1-${month}月`];
  } else {
    // 单月逻辑
    const fullMatch = query.match(/(20\d{2})年(1[0-2]|0?[1-9])月/);
    if (fullMatch) return [`${fullMatch[1]}年${parseInt(fullMatch[2], 10)}月`];

    const yearMatch = query.match(/(20\d{2})/);
    if (yearMatch) return [`${yearMatch[1]}年${month}月`];

    const monthMatch = query.match(/(1[0-2]|0?[1-9])月/);
    if (monthMatch) return [`${year}年${parseInt(monthMatch[1], 10)}月`];

    return [`${year}年${month}月`];
  }
}

🧩 .match() 方法详解

  • .match(regexp) 是 JavaScript 中字符串的方法,用于执行正则表达式匹配。

  • 返回值是一个数组,包含匹配结果;如果没有匹配,则返回 null

  • 示例:

    js 复制代码
    const str = '2024年1-7月';
    const result = str.match(/(20\d{2})年(\d+)-(\d+)月/);
    // result[1] = "2024", result[2] = "1", result[3] = "7"

2.3 高性能模糊匹配与组合生成

🔍 关键优化点

  • 输入小于2个字符时不触发搜索,减少无意义计算
  • 组合生成时提前终止循环,提高性能
  • 按页面类型动态拼接模板顺序

💡 核心代码片段

js 复制代码
getSuggestions(query) {
  const results = [];
  if (!query || query.length < 2) return results;

  const questions = questionMap[this.pageType] || questionMap.monitor;
  for (const item of address) {
    for (const q of questions) {
      const isRange = q.includes('累计售卖情况');
      const smartMonths = parseMonthFromQuery(query, isRange);

      for (const month of smartMonths) {
        let name = '';
        if (this.pageType === 'monitor') {
          name = `${item.name}${month}${q}`;
        } else {
          name = `${month}${item.name}${q}`;
        }

        if (name.includes(query)) {
          results.push({ value: name, id: item.id });
          if (results.length >= 5) return results;
        }

        if (results.length >= 5) return results;
      }

      if (results.length >= 5) return results;
    }

    if (results.length >= 5) return results;
  }

  return results;
}

三、体验优化

✨ 提示优化

  • 使用 el-tooltip 显示完整内容,避免文字被截断
  • 支持高亮匹配关键词(可扩展)
  • 动态切换问题模板(通过 pageType 控制)

四、总结与扩展

🚀 本文核心价值

  • 实现了一个高性能、可扩展、智能补全的自动补全组件
  • 利用正则表达式实现了时间智能推荐与区间解析
  • 通过组合生成 + 提前终止机制优化了大数据下的响应速度
  • 支持不同页面类型的动态模板拼接
相关推荐
前端大卫1 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘1 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare1 小时前
浅浅看一下设计模式
前端
Lee川1 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix2 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人2 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl2 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人2 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼2 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端