vue 自定义右键样式

前言

最近用python写了个小说程序的api,想着用vue作个系统管理数据,脑子里出现的是这个画面:

image

可是这种样式的管理后台已经作了太多了,已经审美疲劳,后面又想了一种类操做系统的UI界面:

主要是靠双击右键来操做,可操做多个模态框,跟操做windows相似,接下来在里面拆出一个功能块来写一篇文章,就是自定义系统默认的右键
自定义右键操做有五个步骤:
  1. 阻止默认右键。
  2. 获取当前右键点击时的x/y坐标,及id
  3. 自定义右键菜单样式及内容,定位在指定的位置后显示。
  4. 返回对应点击目录的事件如:查看删除编辑
  5. 在任何地方点击左键时隐藏右键菜单
关键方法:
@contextmenu.prevent
复制代码

这个是vue内置的,点击右键(阻止默认右键的默认行为)的一个回调方法,他返回了一大串东西这里我用到的是这两个(用于定位显示菜单的x,y位置)javascript

image

可是这里会出现一个问题:css

操做1:
<!--template-->
<ul> <li class="role_list" v-for="(item,index) in role" :key="index" @contextmenu.prevent="rightClick"> <img :src="item.head_portrait" alt=""> <p>{{item.name}}</p> </li> </ul> <!--script--> methods:{ rightClick(e){ <!--这里只能拿到坐标,但拿不到点击对应的id--> console.log(e) } } 复制代码
操做2:
<!--template-->
<ul> <li class="role_list" v-for="(item,index) in role" :key="index" @contextmenu.prevent="rightClick(item.id)"> <img :src="item.head_portrait" alt=""> <p>{{item.name}}</p> </li> </ul> <!--script--> methods:{ rightClick(id){ <!--这里只能拿到id,但拿不到点击对应的坐标--> console.log(id) } } 复制代码
解决方法:

x_indexy_index 是储存在data中的,用于定位模态框位置。
ctrlId 用于给接口处理的依据
showMenu 用于判断是否显示右键菜单前端

<!--template-->
<ul> <li class="role_list" 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)都具有了,由于右键操做不少地方都用到了,因此封装成了一个组件vue

right_menu.vue 组件代码

参数名 注释
x x坐标
y y坐标
showMenu 显示状态
<template>
	<div v-if="show"
	     class="menu_style" 
	     :style="{top:y+'px',left:x+'px'}">
		<ul>
			<!-- 分别传递事件给父元素调用 -->
			<li @click="()=>{$emit('open')}">打开</li>
			<li @click="()=>{$emit('update')}">编辑</li>
			<li @click="()=>{$emit('del')}">删除</li>
		</ul>
	</div>
</template>
<script>
	export default{
		name:'right_menu',
		props:{
			x:{
				type:[Number],
				default:0
			},
			y:{
				type:[Number],
				default:0
			},
			showMenu:{
				type:[Boolean],
				default:false
			}
		},
		data(){
			return {
				show:false,
			}
		},
		methods:{
			// 点击别处时隐藏目录,并传递一个关闭事件
			closeMenu(e){
				this.show = false;
				this.$emit("close",false)
			},
		},
		mounted(){
			// 监听body上的点击
			document.querySelector("body").addEventListener("click",this.closeMenu)
		},
		beforeDestroy(){
			// 移除监听
			document.querySelector("body").removeEventListener("click",this.closeMenu)
		},
		watch:{
			// 监听,保持显示状态与父元素一致
			showMenu(val){
				this.show = val;
			}
		},
	}
</script>
<style scoped>
	.menu_style{
		position: absolute;
		width: 150px;
		background-color: #fff;
		border-radius: 2px;
		box-shadow: 2px 2px 14px #d0d0d0;
	}
	.menu_style>ul>li{
		text-indent: 25px;
		height: 38px;
		line-height: 38px;
		border-bottom: 1px dashed #f0f0f0;
		cursor: pointer;
	}
	.menu_style>ul>li:hover{
		background: #E0EEFF;
	}
</style>
复制代码
组件使用
<template>
    <div class="modal_data_box"> <ul> <li class="role_list" 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> 复制代码
其他文章:

前端经常使用功能小计(持续更新)java

css图片以最长边显示python

flask多图片储存优化flask

flask 实现token机制windows

相关文章
相关标签/搜索