feat(components): [el-message] merge the same content messages(#3836) (#3988)

* style(components): [el-message-box] string does not wrap(#3856)

* feat(components): [el-message] merge the same content messages(#3836)

* feat(components): [el-message] merge the same content messages(#3836)

* feat(components): [el-message] merge the same content messages(#3836)

* refactor(components): el-swtich custom texts and icons

* fix: test

* fix: font size

* fix: example margin

* feat(components): el-switch add inline-prompt support

* revert: paly

* docs: update icons

* feat: add inner text

* fix: switch test

* refactor: icon inline

* feat(components): [el-message] merge the same content messages(#3836)

* feat(components): [el-message] merge the same content messages(#3836)

Co-authored-by: Aex <adaex@qq.com>
This commit is contained in:
表弟
2021-11-05 18:55:40 +08:00
committed by GitHub
parent b13955648b
commit b81bf53f0a
6 changed files with 91 additions and 2 deletions

View File

@@ -63,6 +63,16 @@ Although `message` property supports HTML strings, dynamically rendering arbitra
:::
## grouping
merge messages with the same content.
:::demo Set `grouping` to true and the same content of `message` will be merged.
message/grouping
:::
## Global method
Element Plus has added a global method `$message` for `app.config.globalProperties`. So in a vue instance you can call `Message` like what we did in this page.
@@ -90,6 +100,7 @@ In this case you should call `ElMessage(options)`. We have also registered metho
| on-close | callback function when closed with the message instance as the parameter | function | — | — |
| offset | set the distance to the top of viewport | number | — | 20 |
| appendTo | set the root element for the message | string / HTMLElement | - | document.body |
| grouping | merge messages with the same content, type of VNode message is not supported | boolean | — | false |
## Methods

View File

@@ -0,0 +1,24 @@
<template>
<el-button :plain="true" @click="open">Show message</el-button>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { ElMessage } from 'element-plus'
export default defineComponent({
setup() {
const open = () => {
ElMessage({
message: 'this is a message.',
grouping: true,
type: 'success',
})
}
return {
open,
}
},
})
</script>

View File

@@ -17,6 +17,30 @@ let seed = 1
const message: MessageFn & Partial<Message> = function (options = {}) {
if (isServer) return { close: () => undefined }
if (
!isVNode(options) &&
typeof options === 'object' &&
options.grouping &&
!isVNode(options.message) &&
instances.length
) {
const tempVm: any = instances.find(
(item) =>
`${item.vm.props?.message ?? ''}` ===
`${(options as any).message ?? ''}`
)
if (tempVm) {
tempVm.vm.component!.props.repeatNum += 1
tempVm.vm.component!.props.type = options?.type
return {
close: () =>
((
vm.component!.proxy as ComponentPublicInstance<{ visible: boolean }>
).visible = false),
}
}
}
if (typeof options === 'string' || isVNode(options)) {
options = { message: options }
}

View File

@@ -54,6 +54,14 @@ export const messageProps = buildProps({
type: Number,
default: 0,
},
grouping: {
type: Boolean,
default: false,
},
repeatNum: {
type: Number,
default: 1,
},
} as const)
export type MessageProps = ExtractPropTypes<typeof messageProps>

View File

@@ -19,6 +19,13 @@
@mouseenter="clearTimer"
@mouseleave="startTimer"
>
<el-badge
v-if="repeatNum > 1"
:value="repeatNum"
:type="type ?? 'info'"
class="el-message__badge"
>
</el-badge>
<el-icon v-if="iconComponent" class="el-message__icon" :class="typeClass">
<component :is="iconComponent" />
</el-icon>
@@ -40,9 +47,10 @@
</transition>
</template>
<script lang="ts">
import { defineComponent, computed, ref, onMounted } from 'vue'
import { defineComponent, computed, ref, onMounted, watch } from 'vue'
import { useEventListener, useTimeoutFn } from '@vueuse/core'
import { EVENT_CODE } from '@element-plus/utils/aria'
import ElBadge from '@element-plus/components/badge'
import { ElIcon } from '@element-plus/components/icon'
import { TypeComponents, TypeComponentsMap } from '@element-plus/utils/icon'
@@ -54,6 +62,7 @@ export default defineComponent({
name: 'ElMessage',
components: {
ElBadge,
ElIcon,
...TypeComponents,
},
@@ -111,6 +120,14 @@ export default defineComponent({
visible.value = true
})
watch(
() => props.repeatNum,
() => {
clearTimer()
startTimer()
}
)
useEventListener(document, 'keydown', keydown)
return {

View File

@@ -23,7 +23,6 @@
transition: opacity 0.3s, transform 0.4s, top 0.4s;
background-color: var(--el-message-background-color);
transition: opacity var(--el-transition-duration), transform 0.4s, top 0.4s;
overflow: hidden;
padding: var(--el-message-padding);
display: flex;
align-items: center;
@@ -65,6 +64,12 @@
margin-right: 10px;
}
@include e(badge) {
position: absolute;
top: -8px;
right: -8px;
}
@include e(content) {
padding: 0;
font-size: 14px;