1. 简洁轻量
组件代码简洁明了,没有复杂的逻辑和冗余代码,使其非常轻量级。整个组件只有约 80 行代码,但功能完整,这意味着:
- 加载速度快
- 运行时消耗资源少
- 易于理解和维护
2. 类型安全
使用 TypeScript 接口定义了明确的 Props 类型,提供了:
- 类型检查
- 清晰的属性文档(包括默认值注释)
- 减少运行时错误
3. 高度可配置
尽管代码简洁,但提供了丰富的配置选项:
- 自定义高亮颜色
- 自定义背景色
- 控制是否使用粗体
- 支持区分大小写匹配
- 支持使用自定义 CSS 类
4. 性能优化
组件使用了 Vue 的计算属性进行优化:
highlightStyle
和highlightedText
都是计算属性,只在依赖变化时重新计算- 避免了不必要的重复计算
- 使用正则表达式一次性替换所有匹配项,而不是多次操作 DOM
5. 安全性考虑
组件包含安全处理:
- 使用
escapeRegExp
函数转义正则表达式特殊字符,防止用户输入的关键词破坏正则表达式 - 处理空文本和空关键词的边缘情况
- 使用
v-html
指令安全地渲染 HTML 内容
6. 灵活的样式选项
提供了两种设置高亮样式的方式:
- 内联样式:通过
highlightStyle
计算属性动态生成 - CSS 类:通过
customClass
属性支持外部定义的样式类
7. 易于集成
组件设计使其易于集成到各种场景:
- 可以用于搜索结果高亮
- 可以用于文档内容关键词突出显示
- 可以用于教学内容中重点标记
8. 良好的默认值
组件为所有可选属性提供了合理的默认值:
- 默认高亮颜色为红色 (
#f56c6c
) - 默认背景色为淡红色 (rgba(245, 108, 108, 0.1))
- 默认使用粗体
- 默认不区分大小写
9. 响应式设计
组件充分利用了 Vue 3 的响应式系统:
- 当
text
或keyword
属性变化时,高亮效果会自动更新 - 当样式相关属性变化时,高亮样式会自动更新
10. 代码可读性高
代码结构清晰,变量命名直观,注释完善,使得:
- 新开发者容易理解
- 便于后续维护和扩展
- 可作为学习 Vue 3 组件开发的良好示例
使用示例
新建组件 components/HighlightText/index.vue
<template>
<span class="text" v-html="highlightedText"></span>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
interface Props {
/**
* 要高亮的文本内容
*/
text: string
/**
* 要高亮的关键词
*/
keyword: string
/**
* 高亮的颜色
* @default "#f56c6c"
*/
highlightColor?: string
/**
* 高亮的背景色
* @default "rgba(245, 108, 108, 0.1)"
*/
highlightBgColor?: string
/**
* 是否使用粗体
* @default true
*/
bold?: boolean
/**
* 是否区分大小写
* @default false
*/
caseSensitive?: boolean
/**
* 自定义高亮的CSS类名
*/
customClass?: string
}
const props = withDefaults(defineProps<Props>(), {
highlightColor: '#f56c6c',
highlightBgColor: 'rgba(245, 108, 108, 0.1)',
bold: true,
caseSensitive: false,
customClass: ''
})
// 生成高亮样式
const highlightStyle = computed(() => {
const styles = [
`color: ${props.highlightColor}`,
`background-color: ${props.highlightBgColor}`,
'padding: 0 2px',
'border-radius: 2px'
]
if (props.bold) {
styles.push('font-weight: bold')
}
return styles.join(';')
})
// 生成高亮的HTML
const highlightedText = computed(() => {
if (!props.text || !props.keyword) {
return props.text || ''
}
// 简单文本替换
const flags = props.caseSensitive ? 'g' : 'gi'
const regex = new RegExp(`(${escapeRegExp(props.keyword)})`, flags)
if (props.customClass) {
return props.text.replace(regex, `<span class="${props.customClass}">$1</span>`)
} else {
return props.text.replace(regex, `<span style="${highlightStyle.value}">$1</span>`)
}
})
// 转义正则表达式特殊字符
function escapeRegExp(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}
</script>
<style lang="less" scoped>
.text {
font-size: 14px;
color: #464646;
}
</style>
新建TS components/index.ts
// 引入项目中的全局组件
import HighlightText from './HighlightText/index.vue'
// 全局对象
const allGlobalComponent = { HighlightText }
// 对外暴露插件对象
export default {
install(app) {
// 注册项目全部的全局组件
Object.keys(allGlobalComponent).forEach((key) => {
// 注册为全局组件
app.component(key, allGlobalComponent[key])
})
}
}
main.ts
// 导入插件对象
import globalComponents from './components/index'
//注册
app.use(globalComponents)
全局使用
<!-- 基本用法 -->
<HighlightText text="这是一段示例文本" keyword="示例" />
<!-- 自定义样式 -->
<HighlightText
text="这是一个重要提示"
keyword="重要"
highlight-color="#1677ff"
highlight-bg-color="rgba(22, 119, 255, 0.1)"
/>
<!-- 使用自定义类 去掉父组件的scoped -->
<HighlightText
text="使用自定义CSS类"
keyword="CSS"
custom-class="my-highlight"
/>