闲着周末写了一个react vue3双版本的右键菜单插件

14 阅读3分钟

前言

在Web应用开发中,右键菜单是一个常见的功能。今天,我要分享一个我开发的跨框架右键菜单插件 context-menu-plugin,它不仅支持Vue 3和React,还具备了丰富的功能特性和优秀的交互体验。

核心特性

1. 跨框架支持

这个插件最大的特点是同时支持Vue 3和React两大主流框架。通过抽象共享逻辑和样式,实现了框架无关的核心功能,同时又保持了框架特定的最佳实践。

// Vue 3 使用示例
<template>
<div v-context-menu="menuOptions"> 右键点击此区域 </div> </template> 

// React 使用示例
const [contextMenu] = useContextMenu(); 
<div onContextMenu={contextMenu}> 右键点击此区域 </div>

2. 丰富的功能支持

多级子菜单

支持无限层级的子菜单,每个子菜单都继承父菜单的主题和样式。

主题支持

内置四种主题:

  • Light(默认):清爽的白色主题

  • Dark:深色主题

  • Blue:蓝色主题

  • Green:绿色主题

通过CSS变量实现主题切换,方便用户自定义:

:root {
--cm-light-bg: #ffffff;
--cm-light-text: #333333;
--cm-light-hover: #f5f5f5;
--cm-light-border: #e8e8e8;
}

完整的键盘支持

  • ↑/↓:导航菜单项

  • →:打开子菜单

  • ←:返回上级菜单

  • Enter/Space:选择菜单项

  • Esc:关闭菜单

3. 优秀的交互体验

智能定位

自动检测视口边界,确保菜单始终在可见区域内显示:

// 位置计算逻辑
const position = { x: Math.min(event.clientX, window.innerWidth - menuWidth), y: Math.min(event.clientY, window.innerHeight - menuHeight) };

平滑动画

使用CSS动画提供流畅的过渡效果:

.context-menu { 
animation-duration: var(--cm-animation-duration); animation-name: cmFadeIn;
} 
@keyframes cmFadeIn { 
from { opacity: 0; transform: scale(0.95); } 
to { opacity: 1; transform: scale(1); } }

4. 可访问性支持

遵循WCAG准则,确保菜单对所有用户都可用:

<div role="menu" aria-orientation="vertical" aria-label="上下文菜单" > <div role="menuitem" aria-disabled={disabled} tabIndex={0} > 菜单项 </div>

5. 响应式设计

自动适配移动设备:

@media (max-width: 768px) { .context-menu { min-width: 160px; font-size: 16px; // 更大的字体 .cm-item { padding: 10px 16px; // 更大的点击区域 } } }

技术实现亮点

1. Portal/Teleport技术

为了避免菜单被父元素的overflowz-index影响,使用Portal/Teleport将菜单渲染到body层级:

// React版本
return ReactDOM.createPortal( <ContextMenu />, document.body ); 

// Vue 3版本
<Teleport to="body"> <ContextMenu /> </Teleport>

2. 共享核心逻辑

通过抽象共享代码,确保两个框架版本的行为一致:

src/ 
├── shared/ 
│   ├── contextAware.js  // 上下文感知逻辑 
│   ├── i18n.ts         // 国际化支持 
│   ├── types.ts       // TypeScript类型定义
│   └── utils.js      // 通用工具函数 
├── react/           // React实现 
└── vue3/           // Vue 3实现

3. 性能优化

  • 使用防抖处理窗口调整事件
  • 使用事件委托处理菜单项点击
  • 懒加载子菜单内容

使用方法

安装

Vue 3使用示例

<script setup>
import { useContextMenu } from 'context-menu-plugin/vue3'; 
const menuOptions = { 
items: [ 
{ label: '新建', icon: '📄', 
children: [ 
{ label: '文件', onClick: () => {} },
{ label: '文件夹', onClick: () => {} } ] }, 
{ type: 'separator' }, 
{ label: '刷新', shortcut: 'Ctrl+R', onClick: () => {} } ] }; 
</script> 
<template> 
<div v-context-menu="menuOptions"> 右键点击此区域 </div> 
</template>

React使用示例

import { useContextMenu } from 'context-menu-plugin/react'; 
function App() { 
const [contextMenu] = useContextMenu({ 
items: [ 
{ label: '新建', icon: '📄', children: [ { label: '文件', onClick: () => {} }, 
{ label: '文件夹', onClick: () => {} } ] }, 
{ type: 'separator' }, 
{ label: '刷新', shortcut: 'Ctrl+R', onClick: () => {} } ] }); 
return ( <div onContextMenu={contextMenu}> 右键点击此区域 </div> ); 
}

总结

这个右键菜单插件通过跨框架支持、丰富的功能特性、优秀的交互体验和完善的可访问性支持,为Web应用开发提供了一个强大而灵活的解决方案。无论是Vue 3还是React项目,都能轻松集成并提供一致的用户体验。

未来计划

  1. 添加更多主题预设
  2. 支持更多自定义选项
  3. 添加更多动画效果
  4. 优化移动端体验
  5. 添加更多辅助功能支持