完整代码 + 详细注释
<template>
<div>
<!-- 输入框用于输入关键词 -->
<input v-model="keywords" placeholder="输入关键词,用空格分隔" />
<!-- 显示高亮后的文本 -->
<div v-html="highlightedText"></div>
</div>
</template>
<script>
export default {
data() {
return {
// 原始文本
text: '这是一个示例文本,用于展示多关键词高亮的功能。',
// 用户输入的关键词
keywords: ''
};
},
computed: {
// 计算属性,用于生成高亮后的文本
highlightedText() {
// 如果关键词为空,直接返回原始文本
if (!this.keywords.trim()) {
return this.text;
}
// 将关键词按空格分割成数组
const keywordArray = this.keywords.split(' ');
// 过滤掉空字符串(用户可能输入多个空格)
const nonEmptyKeywords = keywordArray.filter(keyword => keyword.trim());
// 如果没有有效关键词,返回原始文本
if (nonEmptyKeywords.length === 0) {
return this.text;
}
// 去重:避免重复高亮相同的词
const uniqueKeywords = nonEmptyKeywords.filter(
(keyword, index, self) => self.indexOf(keyword) === index
);
// 对关键词中的特殊字符进行转义,避免正则表达式错误
// 例如,如果关键词是 "example*",需要转义为 "example\*"
const escapedKeywords = uniqueKeywords.map(keyword =>
keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
);
// 创建一个正则表达式,匹配所有关键词
// 使用 "gi" 标志:g(全局匹配)和 i(忽略大小写)
const regex = new RegExp(`(${escapedKeywords.join('|')})`, 'gi');
// 使用正则表达式替换文本中的关键词,添加高亮样式
// "$1" 是正则表达式中的捕获组,表示匹配到的关键词
return this.text.replace(regex, '<span style="background-color: yellow;">$1</span>');
}
}
};
</script>
<style>
/* 可以在这里添加一些样式 */
</style>
详细注释
1. 模板部分 (<template>
):
-
<input v-model="keywords" />
:- 使用
v-model
实现双向数据绑定,将用户输入的关键词绑定到keywords
变量。 placeholder
提示用户输入关键词,多个关键词用空格分隔。
- 使用
-
<div v-html="highlightedText"></div>
:- 使用
v-html
指令将高亮后的 HTML 内容渲染到页面上。 - 注意:
v-html
会解析 HTML 字符串,因此需要确保内容安全(避免 XSS 攻击)。
- 使用
2. 脚本部分 (<script>
):
-
data()
:text
: 原始文本内容,需要被高亮的文本。keywords
: 用户输入的关键词,初始为空字符串。
-
highlightedText
计算属性:- 这是一个计算属性,用于动态生成高亮后的文本。
- 它的值会随着
keywords
的变化而自动更新。
逻辑分步解析:
-
检查关键词是否为空:
- 如果
keywords
为空(或全是空格),直接返回原始文本,避免不必要的计算。 - 使用
trim()
去除首尾空格。
- 如果
-
分割关键词:
- 使用
split(' ')
将用户输入的关键词按空格分割成数组。 - 例如,输入
"vue js"
会得到["vue", "js"]
。
- 使用
-
过滤空字符串:
- 用户可能输入多个空格,导致数组中包含空字符串。
- 使用
filter(keyword => keyword.trim())
过滤掉空字符串。
-
检查是否有有效关键词:
- 如果过滤后的数组为空(没有有效关键词),直接返回原始文本。
-
去重:
- 使用
filter
和indexOf
去重,避免重复高亮相同的词。 - 例如,输入
"vue vue"
会去重为["vue"]
。
- 使用
-
转义特殊字符:
- 关键词中可能包含正则表达式的特殊字符(如
*
,+
,?
等),需要转义。 - 使用
replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
对特殊字符进行转义。 - 例如,
"example*"
会被转义为"example\*"
。
- 关键词中可能包含正则表达式的特殊字符(如
为什么需要转义?
正则表达式中的特殊字符(如 *、+、? 等)具有特殊含义。如果不转义,它们会被解释为正则表达式的元字符,导致匹配错误。
例如:*
在正则表达式中表示“前面的字符出现 0 次或多次”。
如果我们希望匹配字面的 *,需要将其转义为 *。
-
创建正则表达式:
- 使用
new RegExp
创建一个正则表达式,匹配所有关键词。 (${escapedKeywords.join('|')})
将关键词用|
连接,表示“或”的关系。- 例如,
["vue", "js"]
会生成正则表达式/(vue|js)/gi
。
- 使用
-
替换文本:
- 使用
replace
方法将匹配到的关键词替换为带有高亮样式的 HTML 标签。 $1
是正则表达式中的捕获组,表示匹配到的关键词。- 例如,
"vue"
会被替换为<span style="background-color: yellow;">vue</span>
。
- 使用
3. 样式部分 (<style>
):
- 可以在这里添加自定义样式,例如调整高亮颜色或输入框样式。
优点:
-
容错性更强:
- 处理了空关键词、重复关键词和特殊字符的情况。
- 避免因无效输入导致的错误。
-
代码更优雅:
- 使用函数式编程(如
filter
、map
)使代码更简洁易读。 - 逻辑分步清晰,易于维护和扩展。
- 使用函数式编程(如
-
性能更好:
- 减少不必要的计算和渲染。
- 只在关键词变化时重新计算高亮文本。
示例:
- 输入关键词:
示例 高亮 功能
,文本中的“示例”、“高亮”和“功能”会被高亮。 - 输入关键词:
示例 示例
,重复的“示例”只会被高亮一次。 - 输入关键词:
示例 *
,特殊字符*
会被正确处理,不会导致正则表达式错误。
使用说明:
- 用户在输入框中输入关键词,多个关键词用空格分隔。
- 页面会实时显示高亮后的文本,匹配到的关键词会以黄色背景高亮显示。