Vue+ElementUI实现给Tab页添加鼠标右键菜单栏

目录标题

  • 一、背景
  • 二、实现思路
    • (一)实现左侧菜单栏的div
    • (二)为Tab页的Tab标签部位绑定右键点击事件。
    • (三)实现弹出右侧菜单栏事件
    • (四)实现右键菜单栏中的每一个点击事件

一、背景

ElementUI官网上提供的Tabs标签只提供了基础的增加和删除标签页的功能,远远不能满足我们的需求。
我们想要对标签页完成更多更能时,就需要自己实现了,比如下图谷歌浏览器的标签页右键功能。
Vue+ElementUI实现给Tab页添加鼠标右键菜单栏_第1张图片
在jQuery配合EasyUI实现此类操作时,我们会首先想到右键菜单栏的方式,那么在使用Vue 和 ElementUI时,我们也将自己实现右键菜单栏的效果,效果图如下:
Vue+ElementUI实现给Tab页添加鼠标右键菜单栏_第2张图片

二、实现思路

(一)实现左侧菜单栏的div

<div v-show="contextMenuVisible">
	<ul :style="{left:left+'px',top:top+'px'}" class="contextmenu">
	    <li><el-button type="text" @click="curTabReload()" size="mini">重新加载</el-button></li>
	    <li><el-button type="text" @click="closeAllTabs()" size="mini">关闭所有</el-button></li>
	    <li><el-button type="text" @click="closeOtherTabs('left')" :disabled="isDisabledCloseLeftBtnFlag" size="mini">关闭左边</el-button></li>
	    <li><el-button type="text" @click="closeOtherTabs('right')" :disabled="isDisabledCloseRightBtnFlag" size="mini">关闭右边</el-button></li>
	    <li><el-button type="text" @click="closeOtherTabs('other')" size="mini">关闭其他</el-button></li>
	</ul>
</div>

使用v-show控制,是否显示菜单栏。
使用disabled控制某种情况下,按钮是否可用。
样式如下:

.contextmenu {
 	width: 100px;
    margin: 0;
    border: 1px solid #ccc;
    background: #fff;
    z-index: 3000;
    position: absolute;
    list-style-type: none;
    padding: 5px 0;
    border-radius: 4px;
    font-size: 14px;
    color: #333;
    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.2);
}
.contextmenu li {
    margin: 0;
    padding: 0px 22px;

}
.contextmenu li:hover {
    background: #f2f2f2;
    cursor: pointer;
}
.contextmenu li button{
   color: #2c3e50;
}

(二)为Tab页的Tab标签部位绑定右键点击事件。

el-tabs标签,生成html后,代码如下图所示:
Vue+ElementUI实现给Tab页添加鼠标右键菜单栏_第3张图片
如果我们直接对el-tabs标签绑定右键点击事件,比如下列代码:

<el-tabs @contextmenu.prevent.native="openContextMenu">
	<el-tab-pane>
		<router-view></router-view>
	</el-tab-pane>
</el-tabs>
<script>
 methods: {
	 openContextMenu(e) {
	 }
}
</script>

这种做法,可以成功绑定右键事件,但却不仅是为Tab标签部分绑定了右键事件。通过查看网页代码,就会发现,Tab的内容部分也被绑定了右键事件,这就会导致Tab内容部分,在浏览器上的表现为,浏览器默认的右键事件也失效了,也就是说无法再进行精准地元素检查的操作了,那将是会非常痛苦的。
解决思路
通过浏览器找到Tab生成标签的class,精准定位需要右键事件的标签部分。
在页面加载完成后,为其绑定上右键事件。
使用如下方式:

mounted() {
	// 获取dom
	let tab_top_dom = document.body.getElementsByClassName("el-tabs__header is-top")
	// 使用原生js 为单个dom绑定鼠标右击事件
	tab_top_dom[0].oncontextmenu = this.openContextMenu
}

注:在vue中获取 dom可以使用ref的方式,但是本例中,Tab的标签部分,并非显式的出现在代码中,而是ElementUI框架内的部分,因此采用了原生的js方式。

(三)实现弹出右侧菜单栏事件

① 获取当前的右键选中的Tab,记录下标签的特征(比如名称)
② 以数据驱动的方式,修改菜单栏div的属性,使其显示。
③附加项:在显示菜单栏div之前,可以对当前Tab所处的位置进行判断,对于最左侧Tab,将“关闭左侧标签页”的按钮设置为不可用;对于最右侧Tab,将“关闭右侧标签页”的按钮设置为不可用。
实现方式如下:

/*
右击事件
  */
openContextMenu(e) {
    e.preventDefault(); //防止默认菜单弹出
     
    let obj = e.srcElement ? e.srcElement : e.target;

    if (obj.id) {
        let currentContextTabId = obj.id.split("-")[1];
        let curIndex = 0;
        for(;curIndex<this.editableTabs.length;++curIndex){
            if(this.editableTabs[curIndex].title == currentContextTabId){
                break;
            }
        }
        if(curIndex<=0){
            this.isDisabledCloseLeftBtnFlag = true
            this.isDisabledCloseRightBtnFlag = false
        }else if(curIndex >= this.editableTabs.length-1){
            this.isDisabledCloseLeftBtnFlag = false
            this.isDisabledCloseRightBtnFlag = true
        }else{
            this.isDisabledCloseLeftBtnFlag = false
            this.isDisabledCloseRightBtnFlag = false
        }
        this.contextMenuVisible = true;
        this.$store.commit("saveCurContextTabId", currentContextTabId);
        this.left = e.clientX;
        this.top = e.clientY + 10;
    }
},

注:
① 原生js方式实现时,要注意阻止弹出浏览器默认的菜单栏,即使用 e.preventDefault();
② 若跨组件了,则可以使用store的方式来对值进行存储和事件响应。

(四)实现右键菜单栏中的每一个点击事件

 
//刷新当前页
curTabReload(){
 	//TODO 重新载入当前标签页
    ... 
}
// 关闭所有标签页
closeAllTabs() {
    //TODO 关闭所有标签
    ... 
    //关闭菜单栏
    this.closeContextMenu()
},
// 关闭其它标签页
closeOtherTabs(par) {
    if (par == "left") {
       //TODO 关闭左侧所有标签
    		... 
    }
    if (par == "right") {
      //TODO 关闭右侧所有标签
    		... 
    }
    if (par == "other") {
        //TODO 关闭其他所有标签
    		... 
    }
     //关闭菜单栏
    this.closeContextMenu()
}

在完成点击事件的动作后,记得关闭菜单栏。

 // 关闭contextMenu
 closeContextMenu() {
	this.contextMenuVisible = false;
 },

详细实现,可参考项目。
项目地址:https://github.com/zhangjiangmse/back_menu.git

你可能感兴趣的:(前端,vue,js,html,css)