
本文介绍一种基于 Vue.js 的轻量级方案,通过将段落中每个单词包裹为 并绑定点击事件,实现单击高亮、再点击取消高亮的交互效果,无需依赖复杂 DOM 遍历或 Selection API。
本文介绍一种基于 vue.js 的轻量级方案,通过将段落中每个单词包裹为 `` 并绑定点击事件,实现单击高亮、再点击取消高亮的交互效果,无需依赖复杂 dom 遍历或 selection api。
要实现在长文本中逐词点击高亮(并支持二次点击取消),核心思路是:将每个独立单词转换为可交互的 元素,并在其上绑定点击逻辑。直接操作 textContent 或尝试链式调用 .add('highlight')(如原代码所示)是无效的——因为字符串对象没有 .add() 方法,且 v-html 渲染后原始文本已脱离 JavaScript 字符串上下文。
✅ 正确实现步骤
-
预处理文本:正则包裹单词
使用计算属性 pageContent,通过正则 /\b(\w+?)\b/g 匹配所有单词边界内的字母数字序列(自动过滤标点),并将每个匹配项包裹为 :computed: { pageContent() { return this.page.replace(/(w+?)/g, '<span>$1</span>'); } } 事件委托:点击即触发样式切换
由于 v-html 渲染的 是动态生成的,我们不能提前为每个 span 绑定事件,而是利用事件冒泡,在父上监听 @click,并通过 e.target 精准捕获被点击的 元素:
methods: { doSomething(e) { // 确保点击目标是 span(避免点击空白处报错) if (e.target.tagName !== 'SPAN') return; if (e.target.style.backgroundColor === 'yellow') { e.target.style.backgroundColor = ''; // 取消高亮 } else { e.target.style.backgroundColor = 'yellow'; // 应用高亮 } console.log('Clicked word:', e.target.textContent); } }
? 为什么用 backgroundColor 而非 color?
原答案使用 color 改变文字颜色,但语义上“高亮”更常指背景色突出(如黄色荧光笔效果),且不影响可读性。本教程采用 background-color: yellow,更符合 UX 直觉。
-
模板渲染:启用 HTML 解析
关键是使用 v-html="pageContent" 渲染处理后的带 的 HTML 字符串:<p v-html="pageContent"></p>
✅ 完整可运行代码
<meta charset="utf-8"><title>Word Highlight Toggle</title><style>
span {
cursor: pointer;
padding: 0 2px; /* 微调视觉间距 */
border-radius: 2px;
transition: background-color 0.15s;
}
/* 可选:添加悬停反馈 */
span:hover {
background-color: #ffeb3b;
}
</style><div id="app">
<p v-html="pageContent"></p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script><script>
var page = 'Lorem ipsum dolor sit amet, cu eum eros vitae persequeris...';
new Vue({
el: '#app',
data: { page: '' },
computed: {
pageContent() {
return this.page.replace(/(w+?)/g, '<span>$1');
}
},
methods: {
doSomething(e) {
if (e.target.tagName !== 'SPAN') return;
const isHighlighted = e.target.style.backgroundColor === 'yellow';
e.target.style.backgroundColor = isHighlighted ? '' : 'yellow';
}
},
created() {
this.page = page;
}
});
</script>
⚠️ 注意事项
- 安全性提醒:v-html 会直接渲染 HTML,若文本来源不可信(如用户输入),需先进行 XSS 过滤(例如使用 DOMPurify),否则存在安全风险。
- 标点处理:当前正则 (w+?) 自动剥离逗号、句号等标点,确保只有纯单词被包裹和响应。
- 性能考虑:对于超长文本(数万字),大量 可能影响渲染性能;如需优化,可结合虚拟滚动或懒加载策略。
- Vue 3 兼容性:本例基于 Vue 2;Vue 3 中 v-html 用法一致,但需改用 createApp 初始化。
该方案简洁、可靠、零依赖,完美满足“点击单词即高亮,再点即取消”的交互需求,是内容标注、阅读辅助类应用的理想基础实现。










