
本文介绍如何在 中仅当用户右键点击预设关键词(如 "hello"、"some" 等)时,精准显示自定义上下文菜单;非关键词区域右键不响应,避免误触发。
本文介绍如何在 `
在 Web 开发中,为文本区域实现「按词触发」的自定义右键菜单,关键在于:不依赖光标选区,而基于鼠标位置附近的实际单词匹配。但需注意:
该策略虽非像素级精准(例如“hello”和“hello!”会被视为不同词),但满足绝大多数业务场景(如敏感词高亮、快捷操作入口),且代码轻量、无依赖、兼容所有浏览器。
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
✅ 实现步骤概览
- 定义关键词数组(specificwords);
- 监听
- 将 textarea 值按空格分割为单词数组,检查是否存在匹配项;
- 若匹配成功,计算鼠标位置并显示自定义菜单;
- 点击页面其他区域时隐藏菜单。
? 核心代码示例
<style>
.custom-context-menu {
z-index: 1100;
display: none;
position: absolute;
list-style: none;
margin: 0;
padding: 0;
border: 1px solid #333;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
border-radius: 4px;
min-width: 160px;
}
.custom-context-menu li {
padding: 8px 16px;
cursor: pointer;
font-size: 14px;
color: #333;
}
.custom-context-menu li:hover {
background-color: #f5f5f5;
color: #1a73e8;
}
</style><textarea rows="4" cols="50">hello This is some text. Click on any word and then do right click</textarea>
<script>
const textarea = document.querySelector('textarea');
const contextMenu = document.querySelector('.custom-context-menu');
const specificwords = ['hi', 'hello', 'yo', 'hey', 'some', 'howdy'];
// 右键事件处理:仅当文本含关键词时激活菜单
textarea.addEventListener('contextmenu', function (e) {
e.preventDefault();
// 提取纯单词(去除标点,统一小写便于匹配)
const cleanText = this.value.replace(/[^\w\s]/g, ' ').toLowerCase();
const words = cleanText.trim().split(/\s+/).filter(w => w.length > 0);
// 检查是否存在任意关键词(不区分大小写)
const hasKeyword = words.some(word => specificwords.includes(word));
if (hasKeyword) {
contextMenu.style.left = `${e.pageX}px`;
contextMenu.style.top = `${e.pageY}px`;
contextMenu.style.display = 'block';
contextMenu.classList.add('on');
}
});
// 点击外部区域关闭菜单
document.addEventListener('click', function (e) {
if (contextMenu.classList.contains('on') &&
e.target !== textarea &&
!contextMenu.contains(e.target)) {
contextMenu.classList.remove('on');
contextMenu.style.display = 'none';
}
});
// 菜单项交互(示例)
contextMenu.addEventListener('click', function (e) {
if (e.target.tagName === 'LI') {
const action = e.target.dataset.action;
const selectedWord = getSelectedWord(textarea); // 辅助函数见下文
console.log(`Action: ${action}, Target word: "${selectedWord}"`);
// 此处可调用 insertEmoji()、highlightWord() 等具体逻辑
}
});
// ? 辅助函数:获取当前光标/选区附近的单词(增强体验)
function getSelectedWord(el) {
const start = el.selectionStart;
const end = el.selectionEnd;
const value = el.value;
// 若有选区,直接返回选中文本
if (start !== end) {
return value.substring(start, end).trim();
}
// 否则尝试提取光标前最近的完整单词
let left = start;
while (left > 0 && /\w/.test(value[left - 1])) left--;
let right = start;
while (right < value.length && /\w/.test(value[right])) right++;
return value.substring(left, right).trim() || '';
}
</script>⚠️ 注意事项与优化建议
- 标点兼容性:示例中使用 replace(/[^\w\s]/g, ' ') 清理标点,确保 "hello!" 能匹配 "hello";如需更严谨匹配(如保留缩写 don't),可改用正则 /[^\p{L}\p{N}'-]+/gu(需现代浏览器支持 Unicode 属性转义)。
- 性能提示:对超长文本(>10KB),频繁 split() 可能轻微影响响应速度,可考虑缓存分词结果或添加防抖。
- 用户体验:当前方案是“全文含关键词即启用”,若需真正「点击某词才触发」,需结合 getSelection() + 光标位置推算,但复杂度显著上升,且在
- 无障碍(a11y):自定义菜单需手动添加 role="menu"、aria-haspopup 及键盘导航支持(如 ArrowUp/Down、Enter),生产环境不可忽略。
通过以上实现,你已拥有一套轻量、稳定、可扩展的关键词驱动右键菜单系统——既满足功能需求,又保持代码清晰与维护友好。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










