最近用python写了个小说程序的api,想着用 vue 做个系统管理数据,脑子里出现的是这个画面:
但是这种样式的管理后台已经做了太多了,已经审美疲劳,后面又想了一种类操作系统的UI界面:
主要是靠 双击 和 右键 来操作,可操作多个模态框,跟操作 windows 类似,接下来在里面拆出一个功能块来写一篇文章,就是 自定义系统默认的右键 。
自定义右键操作有五个步骤: 阻止 默认右键。 获取当前右键点击时的 x / y 坐标,及 id 。 自定义右键菜单样式及内容,定位在指定的位置后显示。 返回对应点击目录的事件如: 查看 、 删除 、 编辑 。 在任何地方点击左键时 隐藏右键菜单 。 关键方法:
@contextmenu.prevent
这个是vue内置的,点击右键(阻止默认右键的默认行为)的一个回调方法,他返回了一大串东西这里我用到的是这两个(用于定位显示菜单的x,y位置)
x_index , y_index 是储存在 data 中的,用于定位模态框位置。
ctrlId 用于给接口处理的依据
showMenu 用于判断是否显示右键菜单
<!--template--> <ul> <li v-for="(item,index) in role" :key="index" @contextmenu.prevent="(e)=>{ x_index = e.layerX; y_index = e.layerY; ctrlId = item.id; showMenu = true; }"> <img :src="item.head_portrait" alt=""> <p>{{item.name}}</p> </li> </ul>
需要的参数(x,y,id)都具备了,因为右键操作很多地方都用到了,所以封装成了一个组件
right_menu.vue 组件代码 参数名 注释 x x坐标 y y坐标 showMenu 显示状态
参数名
注释
x
x坐标
y
y坐标
showMenu
显示状态
组件使用
<template> <div> <ul> <li v-for="(item,index) in role" :key="index" @contextmenu.prevent="(e)=>{ x_index = e.layerX; y_index = e.layerY; ctrlId = item.id; showMenu = true; }"> <img :src="item.head_portrait" alt=""> <p>{{item.name}}</p> </li> </ul> <!--组件--> <right-menu :x="x_index" :y="y_index" :showMenu="showMenu" @close="closeMenu" @open="openDetail" @del="delAttr" @update="updateArr"> </right-menu> </div> </template> <script> // 导入组件 import rightMenu from '../module/right_menu.vue'; export default{ name:"roleModal", components:{rightMenu}, data(){ return { x_index:0, y_index:0, ctrlId:'', showMenu:false, role:[], } }, methods:{ //关闭回调 closeMenu(state){ console.log('关闭') this.showMenu = state; }, //打开详情回调 openDetail(){ console.log('编辑') }, //删除回调 delAttr(){ console.log('删除') }, //编辑回调 updateArr(){ console.log('编辑') }, } } </script>
修复漏洞
d[o_0]b同学发现了一个漏洞,就是当鼠标在屏幕右边点击时,菜单会被遮挡住,这边做了一些调整。
修复前:
//原来的代码 <ul> <li v-for="(item,index) in role" :key="index" @contextmenu.prevent="(e)=>{ x_index = e.layerX; y_index = e.layerY; ctrlId = item.id; showMenu = true; }"> <img :src="item.head_portrait" alt=""> <p>{{item.name}}</p> </li> </ul>
修复后:
//修改后的代码,(由于要判断,所以单独写了个方法,把e跟item都传过去) <ul> <li v-for="(item,index) in role" :key="index" @contextmenu.prevent="(e)=>{ rightClick(e,item) }"> <img :src="item.head_portrait" alt=""> <p>{{item.name}}</p> </li> </ul> //对应的rightClick方法 rightClick(e,item){ // 屏幕可见宽 let clientWidth = document.body.clientWidth; // 菜单宽 let menuWidth = 150; // 点击右键时会返回对应的clientX,用这个值与(clientWidth+菜单宽度)对比,如果大于的话,就把菜单左偏移一个菜单宽 let clickClientX = e.clientX + menuWidth if(clickClientX > clientWidth){ console.log("菜单超出视线范围") this.x_index = e.layerX - menuWidth; }else{ this.x_index = e.layerX; } this.y_index = e.layerY; this.ctrlId = item.id; this.showMenu = true; },
总结