diff --git a/docs/en-US/component/message.md b/docs/en-US/component/message.md
index 561dfc3165..0269e736f1 100644
--- a/docs/en-US/component/message.md
+++ b/docs/en-US/component/message.md
@@ -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
diff --git a/docs/examples/message/grouping.vue b/docs/examples/message/grouping.vue
new file mode 100644
index 0000000000..ef7e7ad1a3
--- /dev/null
+++ b/docs/examples/message/grouping.vue
@@ -0,0 +1,24 @@
+
+ Show message
+
+
+
diff --git a/packages/components/message/src/message-method.ts b/packages/components/message/src/message-method.ts
index 7aa1cb4c19..64e49eaec9 100644
--- a/packages/components/message/src/message-method.ts
+++ b/packages/components/message/src/message-method.ts
@@ -17,6 +17,30 @@ let seed = 1
const message: MessageFn & Partial = 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 }
}
diff --git a/packages/components/message/src/message.ts b/packages/components/message/src/message.ts
index 66c128bf7a..388d69505f 100644
--- a/packages/components/message/src/message.ts
+++ b/packages/components/message/src/message.ts
@@ -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
diff --git a/packages/components/message/src/message.vue b/packages/components/message/src/message.vue
index 35447e5c96..6ffbc505c8 100644
--- a/packages/components/message/src/message.vue
+++ b/packages/components/message/src/message.vue
@@ -19,6 +19,13 @@
@mouseenter="clearTimer"
@mouseleave="startTimer"
>
+
+
@@ -40,9 +47,10 @@