目录
index/.vue
<template>
<div class="menu_table">
<div
class="table_row"
v-for="(item, index) in menuList"
@click="item.disabled !== true && itemClick(item)"
>
<!-- :style="{
'border-top':item.line ===true?'solid 1px rgb(44, 44, 44)':'none'
}" -->
<div class="item_line" v-if="item.line === true"></div>
<div
:class="{
item_disabled: item.disabled === true,
item_denydisabled: item.disabled === false,
}"
>
<!-- {{item.icon.value}} -->
<!--    -->
<div class="item_label"></div>
<!-- <div class="icon_border"> -->
<img
v-if="item.icon && item.icon.show === true && item.icon.type === 'img'"
:src="item.icon.value"
/>
<div class="no_icon" v-if="item.icon === undefined" />
<!-- </div> -->
<div class="icon_blank"></div>
<div class="icon_label" id="menu_item">{{ item.label }}</div>
</div>
</div>
</div>
</template>
<script>
import { removeMenu } from "./menu";
export default {
data() {
return {
clientX: "0px",
clientY: "0px",
};
},
mounted() {
this.init(this.locat.clientX, this.locat.clientY);
window.onmousedown = (event) => {
// event.button===2||
if (event.button === 0) {
if (event.target.id === "menu_item") {
window.onmousedown = null;
} else {
removeMenu();
}
} else if (event.button === 2) {
if ($store().state.window.isContext) {
this.init(event.clientX, event.clientY);
$store().state.window.isContext = false;
}
// this.clientX = event.clientX + "px";
// this.clientY = event.clientY + "px";
}
};
},
props: {
locat: {
type: Object,
default() {
return {};
},
},
params: {
type: Object,
default() {
return {};
},
},
menuList: {
type: Array,
default() {
return [];
},
},
},
methods: {
itemClick(item) {
console.log(item);
item.fn();
removeMenu();
},
init(clientX, clientY) {
const width = document.body.clientWidth;
const height = document.body.clientHeight;
const boxHeight = this.menuList.length * 25;
const boxWidth = 130;
if (clientY + boxHeight > height) {
if (clientY - boxHeight > 0) {
this.clientY = clientY - boxHeight + "px";
} else {
this.clientY = clientY - boxHeight / 2 + "px";
}
} else {
this.clientY = clientY + "px";
}
if (clientX + boxWidth > width) {
if (clientX - boxWidth > 0) {
this.clientX = clientX - boxWidth + "px";
} else {
this.clientX = clientX - boxWidth / 2 + "px";
}
} else {
this.clientX = clientX + "px";
}
},
},
unmounted() {
window.onmousedown = null;
},
};
</script>
<style scoped>
.table_row {
/* border: solid 1px rgb(44, 44, 44); */
width: 130px;
height: 25px;
background: white;
line-height: 25px;
}
/* :hover {
background: #4791db;
color: white;
} */
.item_denydisabled:hover > .icon_label {
background: #4791db;
color: white;
}
.item_denydisabled:hover > .icon_border {
/* border: ridge 1px #4791db;
box-shadow: 0px 0px 5px 2px rgb(0 0 0 / 8%); */
}
.menu_table {
position: absolute;
top: v-bind(clientY);
left: v-bind(clientX);
z-index: 9999999;
overflow: hidden;
/* border: solid 1px #d7d7d7; */
border-radius: 5px;
box-shadow: 0px 0px 5px 2px rgb(0 0 0 / 8%);
}
.item_disabled {
color: #bbcccc;
width: 100%;
height: 100%;
}
.item_denydisabled {
/* text-align: left; */
/* color: red; */
width: 100%;
height: 100%;
}
.item_label {
height: 1px;
display: inline-block;
width: 9px;
vertical-align: bottom;
}
.item_line {
height: 1px;
width: 100px;
/* position:absolute;
top:0; */
/* margin-top:-1px; */
margin-left: 15px;
display: block;
background-color: #e4e7ed;
/* box-shadow: 0px 0px 10px #b9b9b9; */
}
img,
.no_icon {
width: 14px;
height: 14px;
display: inline-block;
vertical-align: middle;
/* margin-top: -5px;
margin-left: 3px; */
}
.icon_border {
width: 17px;
height: 17px;
display: inline-block;
/* border: groove 1px #4791db; */
vertical-align: middle;
}
.icon_blank {
height: 100%;
display: inline-block;
width: 5px;
vertical-align: bottom;
}
.icon_label {
height: 100%;
display: inline-block;
width: 95px;
vertical-align: middle;
}
</style>
menu.js
import { createVNode, render } from "vue";
import menuElement from "./index.vue";
// 定义一个div容器
const div = document.createElement("div");
document.body.appendChild(div);
export default {
addMenu(locat, menuList, params) {
const vnode = createVNode(menuElement, { locat, menuList, params });
// 调用渲染方法:将虚拟节点渲染到dom中
render(vnode, div);
},
};
export const removeMenu = function () {
render(null, div);
};
menuData.js
export default {
viewArr : [
{
label: "左对齐",
tips: "Stop",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/alignLeft_active.svg"
: "statics/icons/proicons/alignLeft.svg",
},
line: false,
fn: (row) => {
this.alignLeft();
},
},
{
label: "水平居中对齐",
tips: "Add",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/alignHorizontalCenter_active.svg"
: "statics/icons/proicons/alignHorizontalCenter.svg",
},
line: false,
fn: (row) => {
this.horizontalCenter();
},
},
{
label: "右对齐",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/alignRight_active.svg"
: "statics/icons/proicons/alignRight.svg",
},
tips: "Edit",
line: false,
fn: (row) => {
this.alignRight();
},
},
{
label: "上对齐",
tips: "Delete",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/alignTop_active.svg"
: "statics/icons/proicons/alignTop.svg",
},
line: false,
fn: (row) => {
this.alignTop();
},
},
{
label: "垂直居中对齐",
tips: "Stop",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/alignVerticalCenter_active.svg"
: "statics/icons/proicons/alignVerticalCenter.svg",
},
line: false,
fn: (row) => {
this.verticalCenter();
},
},
{
label: "下对齐",
tips: "Add",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/alignBottom_active.svg"
: "statics/icons/proicons/alignBottom.svg",
},
line: false,
fn: (row) => {
this.alignBottom();
},
},
{
label: "中心对齐",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/centerAlignment_active.svg"
: "statics/icons/proicons/centerAlignment.svg",
},
tips: "Edit",
line: false,
fn: (row) => {
this.controlCenter();
},
},
{
label: "垂直等间距",
tips: "Stop",
disabled: value >= 3 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 3
? "statics/icons/proicons/verticalEqualSpacing_active.svg"
: "statics/icons/proicons/verticalEqualSpacing.svg",
},
line: true,
fn: (row) => {
this.verticallyEquallySpaced();
},
},
{
label: "水平等间距",
tips: "Add",
disabled: value >= 3 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 3
? "statics/icons/proicons/horizontalEqualSpacing_active.svg"
: "statics/icons/proicons/horizontalEqualSpacing.svg",
},
line: false,
fn: (row) => {
this.horizontallEquidistant();
},
},
{
label: "垂直无间距",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/verticalNoSpace_active.svg"
: "statics/icons/proicons/verticalNoSpace.svg",
},
tips: "Edit",
line: false,
fn: (row) => {
this.nohorizontallEquidistant();
},
},
{
label: "水平无间距",
tips: "Delete",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/horizontalNoSpace_active.svg"
: "statics/icons/proicons/horizontalNoSpace.svg",
},
line: false,
fn: (row) => {
this.noverticallyEquallySpaced();
},
},
{
label: "等宽",
tips: "Add",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/sameWidth_active.svg"
: "statics/icons/proicons/sameWidth.svg",
},
line: true,
fn: (row) => {
this.sameHeight();
},
},
{
label: "等高",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/sameHeight_active.svg"
: "statics/icons/proicons/sameHeight.svg",
},
tips: "Edit",
line: false,
fn: (row) => {
this.sameWidth();
},
},
{
label: "等大小",
tips: "Delete",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/sameSize_active.svg"
: "statics/icons/proicons/sameSize.svg",
},
line: false,
fn: (row) => {
this.sameSize();
},
},
{
label: "上移一层",
tips: "Stop",
disabled: value >= 1 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 1
? "statics/icons/proicons/bringForward_active.svg"
: "statics/icons/proicons/bringForward.svg",
},
line: true,
fn: (row) => {
this.putOnTop();
},
},
{
label: "下移一层",
tips: "Add",
disabled: value >= 1 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 1
? "statics/icons/proicons/bringBackward_active.svg"
: "statics/icons/proicons/bringBackward.svg",
},
line: false,
fn: (row) => {
this.putOnBottom();
},
},
{
label: "移到最上层",
disabled: value === 1 ? false : true,
icon: {
show: true,
type: "img",
value:
value === 1
? "statics/icons/proicons/bringToTop_active.svg"
: "statics/icons/proicons/bringToTop.svg",
},
tips: "Edit",
line: false,
fn: (row) => {
this.moveUpOneLevel();
},
},
{
label: "移到最下层",
tips: "Delete",
disabled: value === 1 ? false : true,
icon: {
show: true,
type: "img",
value:
value === 1
? "statics/icons/proicons/bringToBack_active.svg"
: "statics/icons/proicons/bringToBack.svg",
},
line: false,
fn: (row) => {
this.moveDownOneLevel();
},
},
{
label: "编辑",
disabled: spValue ? false : true,
icon: {
show: true,
type: "img",
value: spValue
? "statics/icons/proicons/edit_active.svg"
: "statics/icons/proicons/edit.svg",
},
tips: "Edit",
line: true,
fn: (row) => {
this.changeNone();
},
},
{
label: "打组",
disabled: value >= 2 ? false : true,
icon: {
show: true,
type: "img",
value:
value >= 2
? "statics/icons/proicons/group_active.svg"
: "statics/icons/proicons/group.svg",
},
tips: "Edit",
line: false,
fn: (row) => {
this.packGroup();
},
},
{
label: "解组",
tips: "Delete",
disabled: spValue ? false : true,
icon: {
show: true,
type: "img",
value: spValue
? "statics/icons/proicons/ungroup_active.svg"
: "statics/icons/proicons/ungroup.svg",
},
line: false,
fn: (row) => {
this.unpackGroup();
},
},
]
}