Skip to content

Commit

Permalink
refactor: calc offset
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Jun 22, 2022
1 parent 6d5b77a commit 762c0e4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 42 deletions.
48 changes: 13 additions & 35 deletions packages/components/message/src/message-method.ts
@@ -1,4 +1,4 @@
import { createVNode, render } from 'vue'
import { createVNode, render, shallowReactive } from 'vue'
import { isClient } from '@vueuse/core'
import {
debugWarn,
Expand Down Expand Up @@ -26,7 +26,7 @@ import type {
MessageQueueItem,
} from './message'

const instances: MessageQueue = []
export const messageInstances: MessageQueue = shallowReactive([])
let seed = 1

// TODO: Since Notify.ts is basically the same like this file. So we could do some encapsulation against them to reduce code duplication.
Expand Down Expand Up @@ -60,29 +60,13 @@ const normalizeOptions = (params?: MessageParams) => {
return normalized as MessageParamsNormalized
}

const MESSAGE_HEIGHT = 48
const MESSAGE_GAP = 16

const getNextOffset = (offset: number) => offset + MESSAGE_HEIGHT + MESSAGE_GAP

const computeOffset = () => {
if (instances.length === 0) return

instances.reduce((prev, next) => {
next.props.offset = prev
return getNextOffset(prev)
}, instances[0].options.offset)
}

const closeMessage = (instance: MessageQueueItem) => {
const idx = instances.indexOf(instance)
const idx = messageInstances.indexOf(instance)
if (idx === -1) return

instances.splice(idx, 1)
messageInstances.splice(idx, 1)
const { handler } = instance
handler.close()

computeOffset()
}

const createMessage = (
Expand All @@ -94,20 +78,11 @@ const createMessage = (
const id = `message_${seed++}`
const userOnClose = options.onClose

let offset: number
const lastInstance = instances[instances.length - 1]
if (lastInstance) {
offset = getNextOffset(lastInstance.vm.offset)
} else {
offset = options.offset
}

const container = document.createElement('div')

const props = {
...options,
zIndex: options.zIndex ?? nextZIndex(),
offset,
id,
onClose: () => {
userOnClose?.()
Expand Down Expand Up @@ -146,7 +121,7 @@ const createMessage = (
},
}

const instance = {
const instance: MessageQueueItem = {
id,
vnode,
vm,
Expand All @@ -165,14 +140,17 @@ const message: MessageFn &
) => {
if (!isClient) return { close: () => undefined }

if (isNumber(messageConfig.max) && instances.length >= messageConfig.max) {
if (
isNumber(messageConfig.max) &&
messageInstances.length >= messageConfig.max
) {
return { close: () => undefined }
}

const normalized = normalizeOptions(options)

if (normalized.grouping && instances.length) {
const instance = instances.find(
if (normalized.grouping && messageInstances.length) {
const instance = messageInstances.find(
({ vnode: vm }) => vm.props?.message === normalized.message
)
if (instance) {
Expand All @@ -184,7 +162,7 @@ const message: MessageFn &

const instance = createMessage(normalized, context)

instances.push(instance)
messageInstances.push(instance)
return instance.handler
}

Expand All @@ -196,7 +174,7 @@ messageTypes.forEach((type) => {
})

export function closeAll(): void {
for (const instance of instances) {
for (const instance of messageInstances) {
instance.handler.close()
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/components/message/src/message.ts
Expand Up @@ -26,7 +26,7 @@ export const messageDefaults = mutable({
onClose: undefined,
showClose: false,
type: 'info',
offset: 20,
offset: 16,
zIndex: 0,
grouping: false,
repeatNum: 1,
Expand Down
33 changes: 27 additions & 6 deletions packages/components/message/src/message.vue
Expand Up @@ -7,6 +7,7 @@
<div
v-show="visible"
:id="id"
ref="messageRef"
:class="[
ns.b(),
{ [ns.m(type)]: type && !icon },
Expand Down Expand Up @@ -44,13 +45,14 @@

<script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue'
import { useEventListener, useTimeoutFn } from '@vueuse/core'
import { useEventListener, useResizeObserver, useTimeoutFn } from '@vueuse/core'
import { TypeComponents, TypeComponentsMap } from '@element-plus/utils'
import { EVENT_CODE } from '@element-plus/constants'
import ElBadge from '@element-plus/components/badge'
import { ElIcon } from '@element-plus/components/icon'
import { useNamespace } from '@element-plus/hooks'
import { messageEmits, messageProps } from './message'
import { messageInstances } from './message-method'
import type { BadgeProps } from '@element-plus/components/badge'
import type { CSSProperties } from 'vue'
Expand All @@ -64,23 +66,37 @@ const props = defineProps(messageProps)
defineEmits(messageEmits)
const ns = useNamespace('message')
const messageRef = ref<HTMLDivElement>()
const visible = ref(false)
const badgeType = ref<BadgeProps['type']>(
props.type ? (props.type === 'error' ? 'danger' : props.type) : 'info'
)
const height = ref(0)
let stopTimer: (() => void) | undefined = undefined
const badgeType = computed<BadgeProps['type']>(() =>
props.type ? (props.type === 'error' ? 'danger' : props.type) : 'info'
)
const typeClass = computed(() => {
const type = props.type
return { [ns.bm('icon', type)]: type && TypeComponentsMap[type] }
})
const iconComponent = computed(
() => props.icon || TypeComponentsMap[props.type] || ''
)
const lastInstance = computed(() => {
const idx = messageInstances.findIndex((instance) => instance.id === props.id)
if (idx <= 0) return undefined
return messageInstances[idx - 1]
})
const lastOffset = computed(() => {
if (!lastInstance.value) return 0
return lastInstance.value.vm.bottom
})
const offset = computed(() => props.offset + lastOffset.value)
const bottom = computed((): number => height.value + offset.value)
const customStyle = computed<CSSProperties>(() => ({
top: `${props.offset}px`,
top: `${offset.value}px`,
zIndex: props.zIndex,
}))
Expand Down Expand Up @@ -121,8 +137,13 @@ watch(
useEventListener(document, 'keydown', keydown)
useResizeObserver(messageRef, () => {
height.value = messageRef.value!.getBoundingClientRect().height
})
defineExpose({
visible,
bottom,
close,
})
</script>

0 comments on commit 762c0e4

Please sign in to comment.