Skip to content
Merged
4 changes: 2 additions & 2 deletions src/menu/head-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ export default defineComponent({
methods: {
renderNormalSubmenu(node: VMenuData[], depth: number) {
if (node.length === 0) return null;

return (
<ul class={[`${this.classPrefix}-head-menu__submenu`, `${this.classPrefix}-submenu`]}>
<t-tabs value={this.activeValues[depth]} onChange={this.handleTabChange}>
{node.map((item) => (
{/* 由于virtual child机制,这里通过vMenu getChild 会有两个相同的节点,故做此处理 */}
{node.slice(0, node.length / 2).map((item) => (
<t-tab-panel value={item.value} label={typeof item.vnode === 'string' ? item.vnode : item.vnode[0].text}>
{item.children && item.children.length > 0 ? this.renderNormalSubmenu(item.children, depth + 1) : null}
</t-tab-panel>
Expand Down
22 changes: 19 additions & 3 deletions src/menu/submenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
reactive,
} from '@vue/composition-api';
import { isFunction } from 'lodash-es';
import { State } from '@popperjs/core';
import props from './submenu-props';
import { renderContent, renderTNodeJSX } from '../utils/render-tnode';
import FakeArrow from '../common-components/fake-arrow';
Expand Down Expand Up @@ -90,8 +91,8 @@ export default defineComponent({
const submenuClass = computed(() => [
`${classPrefix.value}-menu__item`,
`${classPrefix.value}-menu__item-spacer`,
`${classPrefix.value}-menu__item-spacer--${isHead && !isNested.value ? 'bottom' : 'right'}`,
{
[`${classPrefix.value}-menu__item-spacer--right`]: !isHead || isNested.value,
[`${classPrefix.value}-is-disabled`]: props.disabled,
[`${classPrefix.value}-is-opened`]: isOpen.value,
[`${classPrefix.value}-is-active`]: isActive.value,
Expand Down Expand Up @@ -255,12 +256,27 @@ export default defineComponent({
placement = 'bottom-left';
}

// 上下位置变化时,添加 bottom 和 top 类,用于添加 bottom 和 top 伪元素
const placementChange = (state: State) => {
const spacerEl = this.$refs.popupWrapperRef as HTMLElement;
if (!spacerEl) return;

const prefixClassName = `${this.classPrefix}-menu__spacer`;
const isBottom = state.placement.startsWith('bottom');
const isTop = state.placement.startsWith('top');

spacerEl.classList.toggle(`${prefixClassName}--bottom`, isBottom);
spacerEl.classList.toggle(`${prefixClassName}--top`, isTop);
};

const popupWrapper = (
<div
ref="popupWrapperRef"
class={[
`${this.classPrefix}-menu__spacer`,
`${this.classPrefix}-menu__spacer--${!this.isNested && this.isHead ? 'top' : 'left'}`,
{
[`${this.classPrefix}-menu__spacer--left`]: this.isNested || !this.isHead,
},
]}
onMouseenter={this.handleEnterPopup}
onMouseleave={this.handleMouseLeavePopup}
Expand All @@ -270,13 +286,13 @@ export default defineComponent({
);
const realPopup = (
<Popup
popperContentElement="overlay"
{...((this.popupProps ?? {}) as TdSubmenuProps['popupProps'])}
overlayInnerClassName={[...this.overlayInnerClassName]}
overlayClassName={[...this.overlayClassName]}
visible={this.popupVisible}
placement={(this.popupProps as TdSubmenuProps['popupProps'])?.placement ?? (placement as PopupPlacement)}
content={() => popupWrapper}
on={{ 'placement-change': placementChange }}
>
<div ref="submenuRef" class={this.submenuClass}>
{triggerElement}
Expand Down
39 changes: 17 additions & 22 deletions src/popup/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PropType, VNodeDirective } from 'vue';
import { VNodeDirective } from 'vue';
import { createPopper } from '@popperjs/core';
import { debounce } from 'lodash-es';
import { on, off, once } from '../utils/dom';
Expand Down Expand Up @@ -38,13 +38,6 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(

props: {
...props,
/** @private
* @description popper 内容元素,用于自定义 popper 元素时传入
* 可以是 HTMLElement 或者 ref 名称字符串 (如 'overlay')
*/
popperContentElement: {
type: [String, Object] as PropType<string | HTMLElement>,
},
expandAnimation: {
type: Boolean,
},
Expand All @@ -58,7 +51,7 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(
/** popperjs instance */
popper: null as ReturnType<typeof createPopper>,
/** timeout id */
timeout: null,
timeout: null as ReturnType<typeof setTimeout> | null,
hasDocumentEvent: false,
/** if a trusted action (opening or closing) is prevented, increase this flag */
visibleState: 0,
Expand Down Expand Up @@ -200,22 +193,16 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(
methods: {
updatePopper() {
const { $el: triggerEl } = this;
// 支持传入字符串 ref 名称或 HTMLElement
let popperEl: HTMLElement;
if (typeof this.popperContentElement === 'string') {
popperEl = this.$refs[this.popperContentElement] as HTMLElement;
} else {
popperEl = this.popperContentElement || (this.$refs.popper as HTMLElement);
}
const popperEl = this.$refs.popper as HTMLElement;

if (!popperEl || !this.visible) return;
if (this.popper) {
this.popper.update();
return;
}
this.popper = createPopper(triggerEl, popperEl, {
modifiers:
getIEVersion() > 9
modifiers: [
...(getIEVersion() > 9
? []
: [
{
Expand All @@ -227,7 +214,16 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(
gpuAcceleration: false,
},
},
],
]),
{
name: 'onPlacementChange',
enabled: true,
phase: 'main',
fn: ({ state }) => {
this.$emit('placement-change', state);
},
},
],
placement: getPopperPlacement(this.placement as TdPopupProps['placement']),
onFirstUpdate: () => {
this.$nextTick(this.updatePopper);
Expand Down Expand Up @@ -376,9 +372,8 @@ export default mixins(classPrefixMixins, getAttachConfigMixins('popup')).extend(
}
},
onAfterEnter() {
if (this.visible && this.popper) {
// 动画完成后,元素已有正确尺寸,使用 forceUpdate 强制重新运行所有 modifiers
this.popper.forceUpdate();
if (this.visible) {
this.updatePopper();
}
},
onLeave() {
Expand Down
Loading
Loading