说明
使用vue自定义指令特性,来完成对某个item鼠标右击形成自定义菜单
参考地址
几个钩子函数
- bind: 只调用一次,第一次绑定元素使用,做初始化操作
- inserted:被绑定元素掺入父节点时调用
- update: VNode更新时调用
- unbind:调用一次,指令和元素解绑时调用
钩子函数中参数
- el: 指令当前所绑定元素,可直接才做dom(基本会用到)
- bind(只读): 调用一次,做初始化设置
- name: 指令名字,不包含v-, 比如v-loading,这里就是loading
- value: 指定中绑定值
- arg: 传给指令参数,如v-my-directive:foo 中,参数为 "foo"
- modifiers: 一个包含修饰符对象,如v-loading.fullscreen.lock为{ fullscreen: true, lock: true },这在扩张指令功能时有很重作用
- vnode(只读): vue编译生成虚拟dom节点,通过vnode.context可以获取vm实例对象
- oldVnode(只读):上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用.
vue中使用自定义指令,要善于利用H5中的dataset新特性
具体步骤
- 先写一个组件,用来布局右侧菜单的页面样式,同时设置响应式数据rightMenu,提供包含4个数据,status(字符串)/top(字符串)/left(字符串)/menus(数组)
<template>
<div class="rightClickMenu-box flex-row"
:style="{
display: rightMenu.status,
top: rightMenu.top,
left: rightMenu.left
}">
<ul>
<li class="cp" v-for="item in rightMenu.menus" :key="item.id" @click="item.callBack(item.graphId, item.graphName)">
<div class="flex-row flex-h-sb">
<div style="width: 30%;">
<img :src="item.icon" alt="item.text" style="width: 16px;height: 16px;" />
</div>
<div class="flex-row flex-v-center" style="text-align: left;width: 70%;">{{ item.text }}</div>
</div>
</li>
</ul>
</div>
</template>
- 写自定义右击菜单指令
import Vue from 'vue'
import store from '@/store'
// 自定义右击菜单指令
Vue.directive('rightClick', {
bind: function (el, binding) {
// oncontextmenu是源生鼠标右击事件,默认会弹出浏览器自带右键菜单
el.oncontextmenu = function(e) {
const currentModule = store.state.currentModule
if (currentModule !== 'modelFactoryModel') return // 只有[模型]模块,左侧树才能右击自定义菜单
// 处理菜单名称
const { value: menus } = binding
if (menus.length === 0) return
const graphId = e.target.dataset.graphId // 在使用rightClick节点中配置对应graphId的值
const graphName = e.target.dataset.graphName // 在使用rightClick节点中配置对应graphName的值
// 鼠标位置
const X = e.clientX
const Y = e.clientY
menus.forEach(item => {
item.graphId = graphId
item.graphName = graphName
})
store.commit('updateRightMenuStatus', {
status: 'block',
left: `${X}px`,
top: `${Y}px`,
menus
})
return false // 阻止默认行为,阻止浏览器自带右键菜单的弹出
}
}
})
- 在对应item节点dom上使用v-right-click指令,在dom中使用html5中dataset技巧,来处理参数传递的问题
<div v-right-click="menus"
:data-graph-id="item.id" :data-graph-name="item.name"
class="ml8 cm ops-node" style="color: #666666;"
:draggable="nodeType === 'model' ? false : true"
@dragstart="handleDragstart" @dragend="handleDragEnd($event, item)">
{{ item.name }}
</div>