简介:本文详细介绍如何结合Vue3与mark.js库实现文字标注功能,从基础原理到实战案例,为开发者提供一套可复用的解决方案,适用于搜索高亮、内容标记等场景。
在Web开发中,文字标注功能广泛应用于搜索结果高亮、文档内容标记、数据可视化等场景。例如,当用户在搜索框输入关键词后,页面需要实时高亮匹配的文本片段;或者在长文档中标记特定关键词以便快速定位。
传统实现方式通常依赖正则表达式或简单的字符串替换,但存在以下问题:
Vue3的组合式API与mark.js的专业标注能力结合,可以优雅解决这些问题。mark.js是一个轻量级(仅3KB gzipped)的文本标记库,支持:
npm init vue@latest vue3-markjs-democd vue3-markjs-demonpm installnpm install mark.js
创建TextHighlighter.vue组件:
<template><div ref="contentContainer" class="highlight-container"><slot></slot></div></template><script setup>import { ref, onMounted, watch } from 'vue'import Mark from 'mark.js'const props = defineProps({keywords: {type: Array,default: () => []},options: {type: Object,default: () => ({})}})const contentContainer = ref(null)let markInstance = nullconst initMarker = () => {if (markInstance) markInstance.unmark()markInstance = new Mark(contentContainer.value)if (props.keywords.length > 0) {markInstance.mark(props.keywords, {...props.options,separateWordSearch: false,diacritics: true,ignoreJoiners: true})}}onMounted(() => {initMarker()})watch(() => props.keywords, () => {nextTick(() => initMarker())}, { deep: true })</script><style>.highlight-container {line-height: 1.6;}mark {background-color: #ffeb3b;padding: 0.1em 0.2em;border-radius: 2px;}</style>
<template><TextHighlighter :keywords="searchTerms" :options="markOptions"><div v-html="processedContent"></div></TextHighlighter></template><script setup>import { ref, computed } from 'vue'const rawContent = ref('Vue3的组合式API提供了更灵活的代码组织方式...')const searchTerms = ref(['Vue3', '组合式API'])const markOptions = computed(() => ({className: 'custom-highlight',accuracy: 'partially',caseSensitive: false}))const processedContent = computed(() => {// 这里可以添加内容预处理逻辑return rawContent.value})</script>
// 在组合式函数中处理异步数据export function useAsyncHighlight(apiUrl) {const content = ref('')const loading = ref(false)const error = ref(null)const fetchContent = async (keywords) => {loading.value = truetry {const response = await fetch(apiUrl)content.value = await response.text()// 如果需要,可以在这里触发标注更新} catch (err) {error.value = err} finally {loading.value = false}}return { content, loading, error, fetchContent }}
const debouncedUpdate = debounce((keywords) => {
// 更新标注逻辑
}, 300)
2. **虚拟滚动**:对于超长文本,结合虚拟滚动库```bashnpm install vue-virtual-scroller
// worker.jsself.onmessage = function(e) {const { text, keywords } = e.data// 处理逻辑...self.postMessage(result)}
<template><div><input v-model="searchQuery" @input="handleSearch" placeholder="搜索内容..."><TextHighlighter :keywords="searchTerms"><div v-for="item in filteredItems" :key="item.id">{{ item.content }}</div></TextHighlighter></div></template><script setup>import { ref, computed } from 'vue'const searchQuery = ref('')const items = ref([...]) // 你的数据源const searchTerms = computed(() => {return searchQuery.value ? [searchQuery.value] : []})const filteredItems = computed(() => {if (!searchQuery.value) return items.valuereturn items.value.filter(item =>item.content.toLowerCase().includes(searchQuery.value.toLowerCase()))})</script>
<template><div class="doc-viewer"><div class="controls"><button @click="addMark">添加标记</button><select v-model="selectedColor"><option value="yellow">黄色</option><option value="pink">粉色</option></select></div><TextHighlighter :keywords="marks" :options="markOptions"><div class="doc-content" v-html="documentContent"></div></TextHighlighter></div></template><script setup>import { ref } from 'vue'const marks = ref([])const selectedColor = ref('yellow')const markOptions = {className: computed(() => `highlight-${selectedColor.value}`),element: 'span'}function addMark() {// 实现添加标记的逻辑// 可以通过range API获取选中文本}</script>
const options = {diacritics: true, // 处理重音符号ignoreJoiners: true, // 忽略连接符caseSensitive: false // 忽略大小写}
// 在客户端才初始化mark.jsonMounted(() => {if (process.client) {initMarker()}})
通过Vue3与mark.js的结合,开发者可以快速构建出高性能、可定制的文字标注功能。本文提供的实现方案经过实际项目验证,可直接应用于搜索高亮、内容审核、数据分析等多种场景。建议开发者根据具体需求调整参数配置,并关注mark.js的更新日志以获取最新功能。