Skip to content

Commit f9605b7

Browse files
authored
perf: ⚡ 增强 wd-drop-menu 组件,优化遮罩层闪烁 (#974)
1 parent 91776bf commit f9605b7

2 files changed

Lines changed: 50 additions & 13 deletions

File tree

src/uni_modules/wot-design-uni/components/wd-drop-menu-item/wd-drop-menu-item.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<template>
2-
<view v-if="showWrapper" :class="`wd-drop-item ${customClass}`" :style="`z-index: ${zIndex}; ${positionStyle};${customStyle}`">
2+
<view
3+
v-if="showWrapper"
4+
:class="`wd-drop-item ${customClass}`"
5+
:style="`pointer-events: none; z-index: ${zIndex}; ${positionStyle};${customStyle}`"
6+
>
37
<wd-popup
48
v-model="showPop"
59
:z-index="zIndex"
610
:duration="duration"
711
:position="position"
8-
:custom-style="`position: absolute; max-height: 80%;${customPopupStyle}`"
12+
:custom-style="`position: absolute; pointer-events: auto; max-height: 80%;${customPopupStyle}`"
913
:custom-class="customPopupClass"
10-
modal-style="position: absolute;"
11-
:modal="modal"
14+
:modal="false"
1215
:close-on-click-modal="false"
13-
@click-modal="closeOnClickModal && close()"
1416
@before-enter="beforeEnter"
1517
@after-enter="afterEnter"
1618
@before-leave="beforeLeave"
@@ -71,7 +73,6 @@ const showPop = ref<boolean>(false)
7173
const position = ref<PopupType>()
7274
const zIndex = ref<number>(12)
7375
const modal = ref<boolean>(true)
74-
const closeOnClickModal = ref<boolean>(true)
7576
const duration = ref<number>(0)
7677
7778
const { parent: dropMenu } = useParent(DROP_MENU_KEY)
@@ -181,7 +182,6 @@ function handleOpen() {
181182
if (dropMenu) {
182183
modal.value = Boolean(dropMenu.props.modal)
183184
duration.value = Number(dropMenu.props.duration)
184-
closeOnClickModal.value = Boolean(dropMenu.props.closeOnClickModal)
185185
position.value = dropMenu.props.direction === 'down' ? 'top' : 'bottom'
186186
}
187187
emit('open')

src/uni_modules/wot-design-uni/components/wd-drop-menu/wd-drop-menu.vue

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<template>
2-
<view :style="customStyle" :class="`wd-drop-menu ${customClass}`" @click.stop="noop" :id="dropMenuId">
2+
<view :style="customStyle" :class="`wd-drop-menu ${customClass}`" @click.stop.prevent="noop" :id="dropMenuId">
3+
<wd-overlay :show="overlayVisible" :duration="duration" :z-index="12" :custom-style="modalStyle" @click="handleClickOverlay" @touchmove="noop" />
4+
35
<!-- #ifdef MP-DINGTALK -->
46
<view :id="dropMenuId">
57
<!-- #endif -->
@@ -34,23 +36,52 @@ export default {
3436
</script>
3537

3638
<script lang="ts" setup>
37-
import { getCurrentInstance, inject, onBeforeMount, ref, watch } from 'vue'
39+
import { computed, getCurrentInstance, inject, onBeforeMount, ref, watch } from 'vue'
3840
import { closeOther } from '../common/clickoutside'
3941
import { type Queue, queueKey } from '../composables/useQueue'
4042
import { getRect, uuid } from '../common/util'
4143
import { useChildren } from '../composables/useChildren'
4244
import { DROP_MENU_KEY, dropMenuProps } from './types'
45+
import wdOverlay from '../wd-overlay/wd-overlay.vue'
4346
4447
const props = defineProps(dropMenuProps)
4548
const queue = inject<Queue | null>(queueKey, null)
4649
const dropMenuId = ref<string>(`dropMenuId${uuid()}`)
4750
const offset = ref<number>(0)
4851
const windowHeight = ref<number>(0)
52+
const modalStyle = computed(() => {
53+
return props.direction === 'down'
54+
? `top: calc(var(--window-top) + ${offset.value}px); bottom: 0;`
55+
: `top: 0; bottom: calc(var(--window-bottom) + ${offset.value}px)`
56+
})
4957
5058
const { proxy } = getCurrentInstance() as any
5159
5260
const { linkChildren, children } = useChildren(DROP_MENU_KEY)
5361
62+
const showOverlay = computed(() => {
63+
return children.some((child) => child.$.exposed!.getShowPop())
64+
})
65+
66+
const overlayVisible = ref(false)
67+
let overlayTimer: ReturnType<typeof setTimeout> | null
68+
69+
// 延迟关闭遮罩层,避免闪烁
70+
// 小程序中,即使先 fold 再 closeOther 也会有闪烁,使用延迟关闭遮罩层处理
71+
watch(showOverlay, (newVal) => {
72+
if (overlayTimer) {
73+
clearTimeout(overlayTimer)
74+
}
75+
if (newVal) {
76+
overlayVisible.value = true
77+
} else {
78+
overlayTimer = setTimeout(() => {
79+
overlayVisible.value = false
80+
overlayTimer = null
81+
}, 16)
82+
}
83+
})
84+
5485
linkChildren({ props, fold, offset })
5586
5687
watch(
@@ -68,10 +99,7 @@ onBeforeMount(() => {
6899
windowHeight.value = uni.getSystemInfoSync().windowHeight
69100
})
70101
71-
function noop(event: Event) {
72-
event.preventDefault()
73-
event.stopPropagation()
74-
}
102+
function noop() {}
75103
76104
function getDisplayTitle(child: any) {
77105
const { title, modelValue, options, valueKey, labelKey } = child
@@ -114,6 +142,15 @@ function fold(child: any) {
114142
child.$.exposed!.toggle()
115143
})
116144
}
145+
146+
function handleClickOverlay() {
147+
if (props.closeOnClickModal) {
148+
// 关闭所有打开的菜单项
149+
children.forEach((child) => {
150+
child.$.exposed!.close()
151+
})
152+
}
153+
}
117154
</script>
118155

119156
<style lang="scss" scoped>

0 commit comments

Comments
 (0)