Encapsulate the Tree component with the right-click menu
Tree.vue
file
<template>
<div class="tree-container">
<! Lazy ="true" -->
<el-tree
class="_tree"
:data="treeList"
:props="defaultProps"
@node-expand="handleNodeExpand"
@node-click="handleNodeClick"
@node-contextmenu="handleRightClick"
:default-expanded-keys="expandedKeys"
:node-key="nodeKey"
:highlight-current="true"
ref="comnTree"
:style=" `max-height:${treeHeight}px; max-width:${treeWidth}px; overflow-x:auto; } `"
>
<span slot-scope="{ node, data }">
<i :class="data.icon ? data.icon : 'el-icon-folder-opened'"></i>
<span class="tree_label">{{ node.label }}</span>
<span
class="tree_label"
v-if="data.total || data.total === 0"
title="The number"
>({{ data.total }})</span
>
</span>
</el-tree>
<el-popover
placement="right"
width="150"
trigger="manual"
v-model="Flag"
class="popover-intree"
id="contextMenu"
:style="`left:${clientX}px; top:${clientY}PX`"
>
<ul>
<li
v-for="item in contextMenu"
:key="item.id"
class="context-menu"
@click="handleClickMenu(item)"
>
{{ item.name }}
</li>
</ul>
</el-popover>
</div>
</template>
<script>
import { getViewHeight } from "@/utils/getViewHeight.js";
export default {
data() {
return {
clientX: "".clientY: ""
};
},
props: {
treeList: {
type: Array
},
defaultProps: {
type: Object.default() {
return {
children: "children".label: "name"
// isLeaf: "leaf" // page that needs a leaf node}; }},nodeKey: {
// Each tree node is used as a unique identifier. The entire tree should be unique
type: String.default() {
return "menuId"; }},contextMenu: {
type: Array.default() {
let menu = [
{
name: "Add".value: "add"
},
{
name: "Change".value: "edit"
},
{
name: "Delete".value: "del"}];// Tree right-click menu
returnmenu; }},rightFlag: {
type: Boolean.default() {
return false; }},treeHeight: {
type: Number.default() {
return getViewHeight() - 200; }},treeWidth: {
type: Number.default() {
return 237; }},expandedKeys: {
// The default expanded tree node, ids
type: Array.default() {
return[]; }}},computed: {
Flag: {
get() {
return this.rightFlag;
},
set(val) {
this.$emit("updateTreeMenu", val); }}},mounted() {
// Listen, except click yourself, click somewhere else to hide itself
window.addEventListener("click".this.handleClickDoc);
},
methods: {
handleNodeClick(data) {
this.$emit("updateTreeMenu".false); // Hide the right-click menu when clicking on a tree node.
this.$emit("handleNodeClick", data);
},
handleRightClick(event, obj, node, self) {
// Determine where the right-click menu appears
this.clientX = event.offsetX;
this.clientY = event.clientY; // The height should be adjusted according to your layout
this.setCurrTreeNode(obj[this.nodeKey]);
this.$emit("handleRightClick", obj);
},
handleClickMenu(item) {
this.$emit("handleClickTreeMenu", item);
},
handleNodeExpand(data, node, self) {
this.$emit("handleNodeExpand", data);
},
// Select the method of tree node. When the id is modified, the child component can not listen to the change of the id passed by the parent component. The parent component can take the method of actively obtaining the child component to realize the active selection of the tree node after modification.
setCurrTreeNode(id) {
this.$refs["comnTree"].setCurrentKey(id);
},
handleClickDoc(e) {
const contextMenu = document.getElementById("contextMenu");
if(! contextMenu)return; ! contextMenu.contains(e.target) &&this.$emit("updateTreeMenu".false); }},beforeDestroy() {
window.removeEventListener("click".this.handleClickDoc); }}};</script>
<style lang="scss">
.tree-container {
position: relative;
._tree {
color: # 444;
padding-left: 6px;
overflow: auto; // Change the default icon color of the tree, whether the icon is a leaf node or not //span {
// color: $icon_color; / / / /}.is-leaf {
// color: transparent;
// }
.tree_label {
font-size: 14px;
letter-spacing: 1px;
margin-left: 5px; }}.popover-intree {
position: absolute;
ul {
padding: 3px;
}
li {
list-style: none; }}.context-menu {
letter-spacing: 1px;
color: # 222;
cursor: pointer;
height: 30px;
line-height: 30px;
color: # 000;
text-align: center;
&:hover {
border-radius: 2px;
background: #648fdb;
color: #fff; }}.el-popover {
padding: 2px;
min-width: 20px;
border: 1px solid #ebeef5;
border-radius: 0;
box-shadow: 4px 4px 4px -4px rgb(121.118.118); } // Override the active style of tree.el-tree--highlight-current
.el-tree-node.is-current
> .el-tree-node__content {
background: $active_color;
color: #fff; } // Override the tree style to make the landscape beyond the display scrollbar.el-tree > .el-tree-node {
min-width: 100%;
display: inline-block; }}</style>
Copy the code
2. Introduce and use the Tree component that you just encapsulated
- :treeList=”treeList” Binding tree menu list
- :contextMenu=”contextMenu” right-click menu
- :rightFlag=”rightFlag” Whether to display the right menu
- @handlenodeclick =”handleNodeClick” binding tree node is clicked, triggered function;
- @handlerightclick =”handleRightClick” binds a function triggered by right-clicking on a tree node
- @handlecLickTreemenu =”handleClickTreeMenu” bind the function triggered by right click menu
@updateTreeMenu="updateTreeMenu"
Bound to changerightFlag
When, the triggered function
Test. The vue file
<template>
<div>
<my-tree
:treeList="treeList"
:rightFlag="rightFlag"
:defaultProps="defaultProps"
:nodeKey="nodeKey"
@handleNodeClick="handleNodeClick"
@handleRightClick="handleRightClick"
@handleClickTreeMenu="handleClickTreeMenu"
@updateTreeMenu="updateTreeMenu"
></my-tree>
</div>
</template>
<script>
import myTree from "@/components/Tree.vue"; // Introduce the tree.vue component just defined under SRC/Components
export default {
components: {
myTree
},
data() {
return {
treeList: [
// Usually from the background
{
mid: "1".mName: "qqq".subs: [{mid: "2".mName: "aaaa"}}]].rightFlag: false.// Whether to display the right-click menu
defaultProps: {
// Define the display properties. In treeList are subs and mName,
children: "subs".label: "mName"
},
nodeKey: "mid" // The unique flag of the tree, mid, is also the unique flag of each column in the treeList
};
},
methods: {
updateTreeMenu(val) {
this.rightFlag = val;
},
handleNodeClick(data) {
console.log("Tree node is clicked:", data);
},
handleRightClick(obj) {
this.rightFlag = true; // Displays the right-click menu
console.log("Right mouse click on the node", obj);
},
handleClickTreeMenu(item) {
alert(item.name);
this.rightFlag = false; }}};</script>
Copy the code
GetViewHeight:
Getviewheight.js gets the current viewport height
export function getViewHeight() {
let winHeight = 0;
if (window.innerHeight) {
winHeight = window.innerHeight;
} else if (document.body && document.body.clientHeight) {
winHeight = document.body.clientHeight;
}else
if (document.documentElement && document.documentElement.clientHeight) {
winHeight = document.documentElement.clientHeight;
}
return winHeight;
}
Copy the code
The content of props can be determined as required. The final effect is shown in the figure below: