react-contexify右键菜单动态生成

如果菜单数量少,并且没有其他地方需要共用菜单列表,建议参考react-contexify的右键菜单属性disabled不起作用
此文中处理方法相对快捷

关于为何此插件无法根据state动态更新上文中作者已经说明,这里不在赘述

此方法是根据需要展开右键菜单栏目搭配数量无限增加

的数量,性能会不会有问题也没有过多测试,我实际情况就6种组合,不存在太大问题

首先增加菜单数组中的字段用来判断是否显示/禁用

一般情况大概这样

const menu = {menuId: '2',items: [{ key: 1, name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 2, name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 3, name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 4, name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 5, name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 6, name: 'xxxx', handler: ({props}) => { xxxxx(props); }},],};const ContextMenu = () => (<Menu id={menu.menuId}>{roleInfoMenu.items.map(item => (// 这里需要加key,不然要报错<Item key={item.key} onClick={item.handler}>{item.name}</Item>))}</Menu>);const { show } = useContextMenu({id: '2',});const handleContextMenu = (event, node) => {event.preventDefault();show(event,{props: node,});};const rightContextMenu = (e, data) => {e.preventDefault();handleContextMenu(e, data);};return (
<div>****{arr.map(item => {********<ContextMenu />});****
</div>);

首先修改菜单数组,增加一个字段用来和实际内容状态判断是否需要此菜单

const menu = {menuId: '2',items: [{ key: 1, showStatusArr: [0, 1] name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 2, showStatusArr: [0, 3], name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 3, showStatusArr: [2], name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 4, showStatusArr: [4], name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 5, showStatusArr: [0, 5], name: 'xxxx', handler: ({props}) => { xxxxx(props); }},{ key: 6, showStatusArr: [5], name: 'xxxx', handler: ({props}) => { xxxxx(props); }},],};

然后直接改写ContextMenu的生成逻辑,根据条件判断来生成菜单

  ******
const ContextMenu = ({Status}) => (<ContentMenu id={menu.menuId}>{menu.items.map(item => {// 这里需要加key,不然要报错if(item.showStatusArr instanceof Array && item.showStatusArr.includes(Status)){return <Itemkey={item.key}onClick={item.handler}>{item.name}</Item>}})}</ContentMenu>);******
return (
<div>...{arr.map(item => {********<ContextMenu Status={item.Status} />});...
</div>
);

此时出来的效果变成
因为Menu所在的DOM id是一样的,N条数据执行完之会把Menu的内容改写为最后一次渲染的,并且还打乱了Menu的布局
于是就想出了为每条记录单独创建一个id的Menu,执行useContextMenu()时动态为其指定id,这样就能保证每条记录对应的菜单栏目是事先根据状态生成好的,达到伪动态的目的
这做法缺点很明显,有几种组合,就要在右键点击时判断几种然后更新state的值,凭空增加了很多无用代码量

 // 这两个主要是用来作监听触发展开右键菜单操作的,如果是类组件,可以不用存储鼠标点击事件和点击的栏目内容const [rightMenuId, setRightMenuId] = useState();const [rightClickEve, setRightClickEve] = useState();// 这个用来存储右键点击的栏目内容,const [rightClickItem, setRightClickItem] = useState();// 这里同时监听右键点击的对应右键菜单id和右键事件,然后去触发展开ContextMenu的方法useEffect(() => {if(rightMenuId){handleContextMenu(rightClickEve, rightClickItem);}}, [rightMenuId,rightClickEve]);const handleMenu = {draft: 'draftMenu',submit: 'submitMenu',reject: 'rejectMenu',access: 'accessMenu',public: 'publicMenu',report: 'reportMenu',items: [{ key: 'edit', showStatusArr: [0,2], name: <span><EditOutlined />编辑</span>, handler: ({props}) => { rightContentClick({key: 'edit', item: {props}}) }},{ key: 'submit', showStatusArr: [0,2], name: <span><CheckOutlined />提交</span>, handler: ({props}) => { rightContentClick({key: 'submit', item: {props}}) }},{ key: 'delete', showStatusArr: [0,5], name: <span style={{color: 'red'}}><DeleteOutlined />删除</span>, handler: ({props}) => { rightContentClick({key: 'delete', item: {props}}) }},{ key: 'rollback', showStatusArr: [1], name: <span><RollbackOutlined />撤销</span>, handler: ({props}) => { rightContentClick({key: 'rollback', item: {props}}) }},{ key: 'showReason', showStatusArr: [2, 5], name: <span><EyeOutlined />查看原因</span>, handler: ({props}) => { rightContentClick({key: 'showReason', item: {props}}) }},{ key: 'public', showStatusArr: [3], name: <span><NodeExpandOutlined />上架</span>, handler: ({props}) => { rightContentClick({key: 'public', item: {props}}) }},{ key: 'reEdit', showStatusArr: [3], name: <span style={{color: 'red'}}><EditOutlined />重新修改</span>, handler: ({props}) => { rightContentClick({key: 'reEdit', item: {props}}) }},{ key: 'cancel', showStatusArr: [4], name: <span><NodeCollapseOutlined />下架</span>, handler: ({props}) => { rightContentClick({key: 'cancel', item: {props}}) }},{ key: 'update', showStatusArr: [4], name: <span><ArrowUpOutlined />升级模板</span>, handler: ({props}) => { rightContentClick({key: 'update', item: {props}}) }},{ key: 'appeal', showStatusArr: [5], name: <span><SoundOutlined />申诉</span>, handler: ({props}) => { rightContentClick({key: 'appeal', item: {props}}) }},{ key: 'history', showStatusArr: [0,1,2,3,4,5], name: <span style={{color: '#b99c00'}}><HistoryOutlined />操作历史</span>, handler: ({props}) => { rightContentClick({key: 'history', item: {props}}) }},],};const ContextMenu = ({divId, templateStatus}) => (<ContentMenu id={divId}>{handleMenu.items.map(item => {if(item.showStatusArr instanceof Array && item.showStatusArr.includes(templateStatus)){return <Itemkey={item.key}onClick={item.handler}>{item.name}</Item>}})}</ContentMenu>);const { show } = useContextMenu({id: rightMenuId,});const handleContextMenu = (event, node) => {event.preventDefault();show(event,{props: node,});};const onRightClick = (e, item) => {// 由于下面延时触发了handleContexte,不加这行会把浏览器本身右键菜单也触发了e.preventDefault();if(item.templateStatus === 0){setRightMenuId(handleMenu.draft);}else if(item.templateStatus === 1){setRightMenuId(handleMenu.submit);}else if(item.templateStatus === 2){setRightMenuId(handleMenu.reject);}else if(item.templateStatus === 3){setRightMenuId(handleMenu.access);}else if(item.templateStatus === 4){setRightMenuId(handleMenu.public);}else if(item.templateStatus === 5){setRightMenuId(handleMenu.report);}else{setRightMenuId(handleMenu.draft)}// 由于state异步的问题,不能直接在右击时同步去调用,会出现双击右键才能展开的问题// 类组件可以直接写在state的回调函数里,这里用的函数式组件所以在上面钩子里监听变化来调用// handleContextMenu(e, item);};const generatorDivId = (templateStatus) => {if(templateStatus === 0){return handleMenu.draft;}else if(templateStatus === 1){return handleMenu.submit;}else if(templateStatus === 2){return handleMenu.reject;}else if(templateStatus === 3){return handleMenu.access;}else if(templateStatus === 4){return handleMenu.public;}else if(templateStatus === 5){return handleMenu.report;}else{return handleMenu.draft;}};return (
<div>...{arr.map(item => {<div onContextMenu={(e) => onRightClick(e, item)} title='右键点击展开操作菜单'>********<ContextMenu divId={generatorDivId(item.templateStatus)} templateStatus={item.templateStatus} /></div>});...
</div>
);

效果如下


方式不是很优美,不过好歹满足了要求,还是开头第一句话,如果菜单本身数量少,菜单列表也无需json格式的话采取开头文章中作者的方法更简单快捷。

react-contexify 右键菜单动态生成相关推荐

  1. Extjs4.0 开发笔记-desktop开始菜单动态生成方法

    desktop开始菜单动态生成方法: Desktop.html中,在<scripts>中的Ext.onReady之前添加如下: var mArr = [];//这里是保存显示模块的数组va ...

  2. WPF右键菜单动态传值

    菜单 简介 安装 Newtonsoft.Json.dll 1.VS安装 2.网页下载 代码实现 1. 窗体 2.后台代码动态绑定右键菜单以及事件传对象 关键代码 小结 简介 在工作WPF项目中需要给图 ...

  3. 基于vue+element实现多级菜单动态生成

    使用element的NavMenu组件+vue的组件递归实现动态生成菜单. 首先创建对象记录菜单的标题.链接.子集等信息. menus: [{title: "首页",icon: & ...

  4. element ui 菜单 动态生成 导航

    1. 利用饿了么ui 的 导航菜单组件 (el-menu)来结合 后台返回的 菜单数组进行循环嵌套. 2.看如下代码 <el-menu:default-active="activeIn ...

  5. 如何动态添加菜单/菜单项、子菜单、右键菜单

    有关菜单的操作主要用到 CMenu 类,当然也可用相应 API 函数, CMenu 类只是 MFC 对 API 中操作菜单的函数的封装而已. 不过能用类就尽量用类,类的组织方式好呗,代码看着也舒服. ...

  6. Django 权限管理-后台根据用户权限动态生成菜单

    Django权限管理 实现目标: 1.管理用户,添加角色,用户关联角色 2.添加权限.角色关联权限 3.添加动作.权限关联动作 4.添加菜单.权限关联菜单 实现动态生成用户权限菜单(可设置多级菜单嵌套 ...

  7. c# mvc5 view 多层_MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

    稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...

  8. 取消wps右键菜单_wps自动生成论文目录出现错误怎么办

    论文写完了,需要加目录.WPS有智能目录功能,可用它生成的目录,却出错了:内容残缺不全;排版混乱,一是文字缩进多,二是项目编号后面间距过大.怎么也弄不好.令人头痛不已. 经过网上查找方法,自己摸索,找 ...

  9. react将表格动态生成视频列表【代码】【案例】

    只需要创建一个表格,id为videos,react就能将这个表格转换成视频列表,并点击自动播放 index.html <!DOCTYPE html> <html><hea ...

最新文章

  1. 太难了!远程开工第一天:钉钉、企业微信崩了 飞书有点卡
  2. 软件需求工程与UML建模14组14周工作情况
  3. 将py文件打包为exe可执行文件
  4. Json字符串和Json对象的简单总结
  5. Gemini论文笔记
  6. LoadRunner脚本篇
  7. 基于Java的数据采集(终结篇)
  8. mysql索引的类型和查看、添加、修改、删除索引的方法介绍
  9. BasicGames Python 源码解析 02 Amazing
  10. cad的lisp程序大集合_大数据成神之路-Java高级特性增强(CopyOnWriteArraySet)
  11. 无setup.exe情况下安装mysql5.7.28(win10)
  12. Leetcode 最小栈问题
  13. 析构函数无法命中断点. 当前无法命中断点: 没有与此行关联的调试程序的目标代码类型的可执行代码. 可能的原因包括;条件编译, 编译器优化或者......
  14. 在控制台上看苹果手机的LOG
  15. MATLAB 数据显示格式
  16. Dos攻击工具burpsuite完整使用指南
  17. ionic代码压缩与代码混淆
  18. 计算机用户删除文件找回,电脑删除的文件怎么找回?失易得数据恢复帮助找回...
  19. gcc10环境下bwa安装报错的解决方案
  20. 服务器dns被劫持如何修复,dns劫持,教您DNS被劫持如何修复

热门文章

  1. php 批量生成链接,php 生成迅雷链接的简单示例
  2. 4.3_deferred-init
  3. java微信昵称带表情的处理
  4. 2021年如何通过网络赚钱
  5. android 监听多个广播,同一个广播接收器监听多个广播及多个广播接收器监听同一个广播...
  6. KVM虚拟化,云平台
  7. MacBook连接蓝牙鼠标、蓝牙键盘失败的解决方案
  8. mysql 中手动设置事务提交
  9. 查看树莓派I2C设备是否正常
  10. 电影网页制作HTML+CSS