前言
本文将以 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
。 -
示例:
jsconst 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
控制)
四、总结与扩展
🚀 本文核心价值
- 实现了一个高性能、可扩展、智能补全的自动补全组件
- 利用正则表达式实现了时间智能推荐与区间解析
- 通过组合生成 + 提前终止机制优化了大数据下的响应速度
- 支持不同页面类型的动态模板拼接