赞
踩
之前只实现了对el-tree树形控件初步显示右键菜单,今天对其进一步完善,主要实现如下功能:
1.对菜单进行美化,统一成element-ui风格。
2.右键菜单出现后,点击菜单外其余地方可实现对菜单项的隐藏。
3.右键菜单里放置添加节点和删除节点功能,并加以实现。
1.查看element-ui的主调色,及其他类似菜单的实现方式,将风格统一。
2.点击空白处使菜单隐藏
这就需要监听鼠标的点击事件,当所点区域是菜单之外即可实现隐藏。
最初实现方法是: document.addEventListener(‘click’,this.menuHide,false);
此方法的三个参数含义为:
1:必须,字符串,指定事件名;
2:必须,指定要事件触发时执行的函数;
3:可选,布尔值,指定事件执行的阶段,在冒泡或者捕获阶段执行。(true为捕获,false为冒泡)
menuHide(e){
console.log("我被执行了!!!");
console.log("!!!!!!!!!!!!!!e.targetName=",e.target.nodeName);
if(!this.$refs.menu.contains(e.target)){
console.log(e.target);
console.log("right!!!!!!!!!");
this.menuVisible = false;
}
},
通过监听机制給当前文档document添加了一个click监听事件,但el-tree,但后来发现在el-tree节点上,点击右键菜单出现,此时再点击树上其他节点,发现菜单并未正确隐藏。于是查看打印信息。点击右击事件时,根本就不能在外层监听到click左键事件,menucHide并未被调用,当然也就不能实现对右键菜单的隐藏!
原因:事件冒泡机制!
el-tree中封装了右键和click(即左键)事件,因此考虑到冒泡机制,为了避免外层的click事件影响到本身的click事件,它做了一些特殊的处理,强制覆盖了外层的click事件。因此我们在通过watch监听click事件,在el-tree之外的地方是有效的,但是在el-tree上不能够检测到click而成功隐藏菜单。
解决方法:
直接利用el-tree本身方法nodeclick(),利用v-show实现对右键菜单的隐藏。
3.右键菜单选项“增加”及“删除”功能的实现
(1)增加
增加功能利用其方法append()和remove()为tree的节点追加和删除一个子节点。不过将两个功能在右键菜单项中实现。
第一次实现如下:
<el-tree :data="data5" node-key="id" default-expand-all :expand-on-click-node="false" @node-contextmenu = "rihgtClick" > <span class="custom-tree-node" slot-scope="{ node, data }"> <span> <i v-if ="node.data.flag" :class="node.icon[0]"> </i> <i v-else-if="node.data.flag === false" :class = "node.icon[1]"></i> {{ node.label }} </span> <span> //定义菜单及菜单项的操作 <div v-show = "menuVisible" ref="menu"> <ul id = "menu"> <li tabindex="-1" class="menu__item" id="menu-4994-1-0" @click = "() => append(data)"> <i class="el-icon-circle-plus-outline"></i> 添加 </li> <li tabindex="-1" class="menu__item" id="menu-4994-1-1"> <i class="el-icon-edit"></i> 修改 </li> <li tabindex="-1" class="menu__item" id="menu-4994-1-2" @click = "() => remove(data)"> <i class="el-icon-remove-outline"></i> 删除 </li> </ul> </div> </span> </span> </el-tree>
效果为:
右键点击时发现可视范围内有多个菜单项,主要的一个菜单,右边还有六个菜单。分析后,发现el-tree中一共有七个节点,这里出现了七个菜单。再查看代码,菜单块放在slot-scope中,树节点的生成也是通过slot-scope循环产生的,这也正是出现多个菜单的原因。
由此又引发了另一个问题:
如上图所示:在一级菜单处右键添加可正确添加至two一级1下的字节点,但在第二个一级节点two一级2处右键添加发现仍旧添加至之前地方。仔细一看才发现是因为,每个节点对应生成了一个右键菜单,于是点击刚刚多个菜单中,two一级2对应的菜单中添加事件,发现果然正确添加。
**解决方法:**显然菜单是不能放至el-tree内层中的,于是放至外层。但是很快发现,由于我们要获取每个节点信息,放置外层后,获取每个节点的信息就是一个关键点。
于是打印输出相关信息:
如上图所示:可以看到右键时传递的参数中有与append()方法需要的参数相同,于是我们可以利用右键点击事件将该参数存储至一个变量,之后再传递給append方法,恩,就是这样。当涉及到的需要共享多个数据时,可以考虑使用vuex来管理该参数的传递和获取。
同理,remove()方法删除节点也类似迎刃而解了。
发现右键菜单的定位仍旧有问题,当滑动鼠标改变当前页面位置时,再次于树节点上右键位置偏离的厉害,并不正确。
---------------------------------------分割线2019528---------------------------------------------
关于遗留问题,是因为滚动条出现时,新增滚动条,而定位未将隐藏的部分长度计算在内,始终以无滚动条时定位为准,因此看到菜单位置显示始终是未出现滚动条之前的位置。也就是错误和正确间隔着一个滚动条的距离(笑哭)。
查询事件中的鼠标定位:
event.clientY:页面可视区域的Y偏移量(不包括工具栏、搜索栏等),并且与页面滚动无关,滚动后的clientY值不变。
event.pageY:页面坐标Y,pageY = clientY + 页面滚动高度。
根因找到,因此处理方法两种:
(1)直接使用pageY来进行定位,修改原代码为:
menu.style.left = event.pageX + 20 + ‘px’;
menu.style.top = event.pageY + -10 + ‘px’;
(2)在组件mounted钩子函数中增加监听函数,滑动滚轮浏览网页的时候网页隐藏在屏幕上方的距离存储至变量中保存。右键菜单定位处,再加上该距离即可。另外,销毁该组件时,移除监听事件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。