-
-
Save Fl0pZz/bb25c47a282a6bfe62710a168d895a93 to your computer and use it in GitHub Desktop.
Реализация стека уведомлений на vuex, vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { PUSH_NOTICE, DELETE_NOTICE, CHANGE_NOTICE } from './../mutation-types' | |
const state = { | |
/** | |
* structure of notice obj: | |
* { | |
* type: 'error'|'notification', | |
* messages: [], | |
* action: 'nothing'|'close'|'waiting' <-- action in notification | |
* } | |
*/ | |
notices: new Map(), | |
id: 0, // идентификатор, который будет присвоен следующему уведомлению | |
old_id: null, // идентификатор, которым обладает самое старое уведомление | |
size: 0 | |
} | |
// getters | |
const getters = { | |
isEmpty: state => (state.size === 0), | |
getId: state => state.id, | |
getOldId: state => state.old_id | |
} | |
// mutations | |
const mutations = { | |
[PUSH_NOTICE] (state, notice) { | |
if (state.old_id === null) { | |
state.old_id = state.id | |
} | |
/* | |
Каждому уведомлению присваивается уникальный id, по которым компоненты могут управлять временем жизни уведомления | |
Например форма входа в аккаунт: если в поле email было введен не email, то вывесем уведомление и | |
как только ошибка исправлена, уведомление можно скрыть | |
*/ | |
state.notices.set(state.id++, notice) | |
state.size = state.notices.size | |
}, | |
[CHANGE_NOTICE] (state, { id, notice }) { | |
state.notices.set(id, notice) | |
}, | |
[DELETE_NOTICE] (state, id) { | |
if (state.notices.has(id)) { | |
state.notices.delete(id) | |
state.size = state.notices.size | |
} | |
if (state.notices.size !== 0) { | |
/* | |
если в очереди еще есть уведомления, то переходим к новому | |
*/ | |
state.old_id++ | |
} else { | |
/* | |
чтобы не было траблов, когда уведомлений нет, но old_id и id не равны 0 | |
*/ | |
state.id = 0 | |
state.notices.clear() | |
state.old_id = null | |
state.size = 0 | |
} | |
} | |
} | |
// actions | |
const actions = { | |
asyncPushNotice ({ getters, commit }, notice) { | |
/** | |
* Пушим новое сообщение и получаем его id | |
*/ | |
let id = getters.getId | |
commit(PUSH_NOTICE, notice) | |
return id | |
}, | |
asyncShiftNotice ({ state, commit, getters }, id = null) { | |
/** | |
* Достаем самое старое сообщение или то, которое соответствует нужному id. | |
* ВАЖНО! удаляем сообщение, чтобы не было неопределенного поведения при совместном доступе к уведомлению с одним id | |
*/ | |
let notice = null | |
if (id === null) { | |
notice = state.notices.get(getters.getOldId) | |
} else { | |
notice = state.notices.get(id) | |
} | |
commit(DELETE_NOTICE, getters.getOldId) | |
return notice | |
} | |
} | |
export default { | |
state, | |
getters, | |
mutations, | |
actions | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mapGetters, mapActions } from 'vuex' | |
// import store from './../../store/store' | |
// const MAX_AMOUNT_NOTIFICATION = 5 | |
const TIME_SHOW_NOTIFICATION = 4000 | |
const TIME_SHOW_ERROR = 3000000 | |
export default { | |
name: 'notification', | |
data: () => { | |
return { | |
count: 0 | |
} | |
}, | |
watch: { | |
isEmpty: function (empty) { | |
if (!empty) { | |
this.creator() | |
} | |
} | |
}, | |
computed: { | |
...mapGetters([ | |
'isEmpty' | |
]) | |
}, | |
mounted () { | |
if (!this.isEmpty) { | |
this.creator() | |
} | |
}, | |
methods: { | |
creator () { | |
let $this = this | |
while (!this.isEmpty) { | |
this.shiftNotice() | |
.then((notice) => { | |
switch (notice.type) { | |
case 'error': | |
Materialize.toast($this.createNotification(notice), TIME_SHOW_ERROR) | |
break | |
case 'notification': | |
Materialize.toast($this.createNotification(notice), TIME_SHOW_NOTIFICATION) | |
break | |
default: | |
console.log('Что ты мне дал?!') | |
} | |
}) | |
} | |
}, | |
createNotification ({ messages, action }) { | |
let notice = '' | |
switch (action) { | |
case 'waiting': | |
break | |
case 'close': | |
notice = '<i class="material-icons right">close</i>' | |
break | |
case 'nothing': | |
break | |
default: | |
console.log('wtf?') | |
} | |
messages.forEach((message, i, messages) => { | |
notice += `${message}` | |
if (messages.length > 1) { | |
notice += '<br>' | |
} | |
}) | |
return notice | |
}, | |
...mapActions({ | |
shiftNotice: 'asyncShiftNotice' | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment