From 635814d1d3263e16e53411a1009ef46b379261d7 Mon Sep 17 00:00:00 2001
From: 07akioni <07akioni2@gmail.com>
Date: Fri, 6 Dec 2019 23:09:30 +0800
Subject: [PATCH] refactor(message): support theme change when active
---
.../components/message/enUS/aboutTheme.md | 23 ++++++++++
.../components/message/enUS/index.md | 1 +
.../components/message/enUS/timing.md | 1 +
packages/common/Message/index.js | 2 +-
packages/common/Message/src/Message.vue | 7 ++-
.../common/Message/src/MessageEnvironment.vue | 23 ++++++++++
packages/common/Message/src/main.js | 44 ++++++++++++++-----
7 files changed, 87 insertions(+), 14 deletions(-)
create mode 100644 demo/documentation/components/message/enUS/aboutTheme.md
create mode 100644 packages/common/Message/src/MessageEnvironment.vue
diff --git a/demo/documentation/components/message/enUS/aboutTheme.md b/demo/documentation/components/message/enUS/aboutTheme.md
new file mode 100644
index 000000000..7ab0f5c41
--- /dev/null
+++ b/demo/documentation/components/message/enUS/aboutTheme.md
@@ -0,0 +1,23 @@
+# Caveat About Theme
+Wherever you use `this.$NMessage` to generate a message, if you don't specify the theme of it, the theme of created message will follow the outer-most ascendant Config Provider of `this`. Making the message's theme as same as its invoking component instance will cause chaos.
+```html
+
+ You can change the theme while the message is active
+
+```
+
+```js
+export default {
+ data() {
+ return {}
+ },
+ methods: {
+ emitInfo() {
+ this.$NMessage.info(
+ "I don't know why nobody told you how to unfold your love",
+ { duration: 5000 }
+ )
+ }
+ }
+}
+```
\ No newline at end of file
diff --git a/demo/documentation/components/message/enUS/index.md b/demo/documentation/components/message/enUS/index.md
index 352e9f18d..081a01e7e 100644
--- a/demo/documentation/components/message/enUS/index.md
+++ b/demo/documentation/components/message/enUS/index.md
@@ -3,4 +3,5 @@
basic
icon
timing
+about-theme
```
\ No newline at end of file
diff --git a/demo/documentation/components/message/enUS/timing.md b/demo/documentation/components/message/enUS/timing.md
index 8463a6c47..097b46b08 100644
--- a/demo/documentation/components/message/enUS/timing.md
+++ b/demo/documentation/components/message/enUS/timing.md
@@ -1,4 +1,5 @@
# Timing
+Specify the duration of messages.
```html
Last for 5 second
diff --git a/packages/common/Message/index.js b/packages/common/Message/index.js
index 10460fe44..a2ff7e565 100644
--- a/packages/common/Message/index.js
+++ b/packages/common/Message/index.js
@@ -1,5 +1,5 @@
import Message from './src/main.js'
-import { install } from '../../utils/installThemeableProperty'
+import { install } from '../../utils/installThemeAwarableProperty'
Message.install = function (Vue) {
Message.Vue = Vue
diff --git a/packages/common/Message/src/Message.vue b/packages/common/Message/src/Message.vue
index 80a307cad..9d446eea6 100644
--- a/packages/common/Message/src/Message.vue
+++ b/packages/common/Message/src/Message.vue
@@ -14,6 +14,10 @@ export default {
content: {
type: String,
default: ''
+ },
+ theme: {
+ type: String,
+ default: null
}
},
computed: {
@@ -38,12 +42,11 @@ export default {
} else if (this.type === 'warning') {
icon = h(mdAlert)
}
- const theme = this.option.theme
return h('div', {
staticClass: 'n-message',
class: {
[`n-message--${this.type}`]: true,
- [`n-${theme}-theme`]: theme
+ [`n-${this.theme}-theme`]: this.theme
}
}, [
h('div', {
diff --git a/packages/common/Message/src/MessageEnvironment.vue b/packages/common/Message/src/MessageEnvironment.vue
new file mode 100644
index 000000000..176006763
--- /dev/null
+++ b/packages/common/Message/src/MessageEnvironment.vue
@@ -0,0 +1,23 @@
+
diff --git a/packages/common/Message/src/main.js b/packages/common/Message/src/main.js
index e748db595..40f1ceb8b 100644
--- a/packages/common/Message/src/main.js
+++ b/packages/common/Message/src/main.js
@@ -1,4 +1,4 @@
-import Message from './Message'
+import MessageEnvironment from './MessageEnvironment'
function attachMessageContainer () {
let messageContainer = document.querySelector('.n-message-container')
@@ -11,7 +11,15 @@ function attachMessageContainer () {
return messageContainer
}
-function mountMessage (container, el, option) {
+function detachMessageContainer () {
+ let messageContainer = document.querySelector('.n-message-container')
+ if (messageContainer) {
+ messageContainer.parentElement.removeChild(messageContainer)
+ }
+}
+
+function mountMessage (container, instance, option, instances) {
+ const el = instance.$el
el.classList.add('n-message--enter')
container.appendChild(el)
el.getBoundingClientRect()
@@ -19,7 +27,12 @@ function mountMessage (container, el, option) {
setTimeout(function () {
setTimeout(function () {
setTimeout(function () {
+ instance.$destroy()
+ instances.delete(instance)
container.removeChild(el)
+ if (!instances.size) {
+ detachMessageContainer()
+ }
}, option.vanishTransitionTimeout)
el.classList.add('n-message--leave')
}, option.duration)
@@ -60,33 +73,42 @@ const NMessage = {
},
theme: null,
attachMessageContainer,
+ instances: new Set(),
+ handleThemeChange (theme) {
+ for (const instance of this.instances) {
+ instance.theme = theme
+ }
+ },
notice (content, option) {
const messageContainer = this.attachMessageContainer()
- const messageCell = new this.Vue({
- ...Message,
- propsData: { option: { theme: this.theme, ...option }, content }
- }).$mount()
- mountMessage(messageContainer, messageCell.$el, mixinOption(option))
+ const messageInstance = new this.Vue(MessageEnvironment)
+ messageInstance.option = option
+ messageInstance.content = content
+ messageInstance.theme = this.theme
+ messageInstance.$mount()
+ this.instances.add(messageInstance)
+ mountMessage(messageContainer, messageInstance, mixinOption(option), this.instances)
+ return messageInstance
},
info (content, option) {
option = mixinOption(option)
option.type = 'info'
- this.notice(content, option)
+ return this.notice(content, option)
},
success (content, option) {
option = mixinOption(option)
option.type = 'success'
- this.notice(content, option)
+ return this.notice(content, option)
},
warning (content, option) {
option = mixinOption(option)
option.type = 'warning'
- this.notice(content, option)
+ return this.notice(content, option)
},
error (content, option) {
option = mixinOption(option)
option.type = 'error'
- this.notice(content, option)
+ return this.notice(content, option)
}
}