121 lines
2.8 KiB
Vue
121 lines
2.8 KiB
Vue
<script lang="ts">
|
|
export default {
|
|
name: "LaySubMenu",
|
|
};
|
|
</script>
|
|
|
|
<script setup lang="ts">
|
|
import {
|
|
computed,
|
|
inject,
|
|
onBeforeUnmount,
|
|
ref,
|
|
Ref,
|
|
useSlots,
|
|
watch,
|
|
} from "vue";
|
|
import { onClickOutside } from "@vueuse/core";
|
|
import LayTransition from "../transition";
|
|
|
|
export interface LaySubMenuProps {
|
|
id: string;
|
|
title?: string;
|
|
}
|
|
|
|
const slots = useSlots();
|
|
const props = defineProps<LaySubMenuProps>();
|
|
|
|
const isTree: Ref<boolean> = inject("isTree") as Ref<boolean>;
|
|
const selectedKey: Ref<string> = inject("selectedKey") as Ref<string>;
|
|
const openKeys: Ref<string[]> = inject("openKeys") as Ref<string[]>;
|
|
const isCollapse: Ref<boolean> = inject("isCollapse") as Ref<boolean>;
|
|
const isCollapseTransition: Ref<boolean> = inject(
|
|
"isCollapseTransition"
|
|
) as Ref<boolean>;
|
|
|
|
const isOpen = computed(() => {
|
|
return openKeys.value.includes(props.id);
|
|
});
|
|
|
|
const subMenuRef = ref<HTMLElement>();
|
|
const position = ref<String>();
|
|
|
|
watch(isOpen, () => {
|
|
if (isOpen.value && position.value !== "left-nav") {
|
|
setTimeout(setPosition, 0);
|
|
}
|
|
});
|
|
|
|
const openHandle = function () {
|
|
if (!isCollapse.value) {
|
|
if (openKeys.value.includes(props.id)) {
|
|
openKeys.value.splice(openKeys.value.indexOf(props.id), 1);
|
|
} else {
|
|
openKeys.value.push(props.id);
|
|
}
|
|
}
|
|
};
|
|
|
|
const setPosition = function () {
|
|
if (!isTree.value || !subMenuRef.value) {
|
|
return;
|
|
}
|
|
const offsetWidth = subMenuRef.value.offsetWidth;
|
|
if (
|
|
window.innerWidth <
|
|
subMenuRef.value.getBoundingClientRect().left + offsetWidth + 10
|
|
) {
|
|
position.value = "left-nav";
|
|
} else {
|
|
position.value = "";
|
|
}
|
|
};
|
|
|
|
onClickOutside(subMenuRef, (event: PointerEvent) => {
|
|
if (!isTree.value) {
|
|
let index = openKeys.value.indexOf(props.id);
|
|
if (index != -1) {
|
|
openKeys.value.splice(index, 1);
|
|
}
|
|
}
|
|
});
|
|
|
|
window.addEventListener("resize", setPosition);
|
|
onBeforeUnmount(() => window.removeEventListener("resize", setPosition));
|
|
</script>
|
|
|
|
<template>
|
|
<li class="layui-nav-item">
|
|
<a href="javascript:void(0)" @click="openHandle()">
|
|
<i>
|
|
<slot v-if="slots.icon" name="icon"></slot>
|
|
</i>
|
|
<span>
|
|
<slot v-if="slots.title" name="title"></slot>
|
|
</span>
|
|
<i
|
|
:class="[isOpen && !isTree ? 'layui-nav-mored' : '']"
|
|
class="layui-icon layui-icon-down layui-nav-more"
|
|
></i>
|
|
</a>
|
|
<template v-if="isTree">
|
|
<lay-transition :enable="isCollapseTransition">
|
|
<div v-if="isOpen">
|
|
<dl class="layui-nav-child">
|
|
<slot></slot>
|
|
</dl>
|
|
</div>
|
|
</lay-transition>
|
|
</template>
|
|
<template v-else>
|
|
<dl
|
|
ref="subMenuRef"
|
|
class="layui-nav-child layui-anim layui-anim-upbit"
|
|
:class="[{ 'layui-show': isOpen }, position]"
|
|
>
|
|
<slot></slot>
|
|
</dl>
|
|
</template>
|
|
</li>
|
|
</template>
|