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) } }