refactor(message): support theme change when active

This commit is contained in:
07akioni 2019-12-06 23:09:30 +08:00
parent 7c3f6b9aef
commit 635814d1d3
7 changed files with 87 additions and 14 deletions

View File

@ -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
<n-button @click="emitInfo">
You can change the theme while the message is active
</n-button>
```
```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 }
)
}
}
}
```

View File

@ -3,4 +3,5 @@
basic
icon
timing
about-theme
```

View File

@ -1,4 +1,5 @@
# Timing
Specify the duration of messages.
```html
<n-button @click="emitInfo">
Last for 5 second

View File

@ -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

View File

@ -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', {

View File

@ -0,0 +1,23 @@
<script>
import NMessage from './Message'
export default {
data () {
return {
theme: null,
content: null,
option: null
}
},
render (h) {
console.log('theme', this.theme)
return h(NMessage, {
props: {
theme: this.theme,
content: this.content,
option: this.option
}
})
}
}
</script>

View File

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