Here is a small typescript module:
import { ref } from 'vue'
import { i18n } from '~/i18n'
import { ElMessageBoxOptions } from 'element-plus'
const { t } = i18n.global
export const toasts = ref<ElMessageBoxOptions[]>([])
export const showToast = async (options: ElMessageBoxOptions) => {
console.log("pushing", options)
toasts.value.push(options)
}
export const showError = async (e: any) => {
var message : string
try {
message = t("" + e)
} catch (e) {
console.log(""+e)
message = t("general.something_strange_happened")
}
showToast({
type: 'error',
message: t('general.error') + " " + message,
})
}
export const showSuccess = async (message: string) => {
showToast({
type: 'success',
message: message
})
}
And here is a vue component called Toast
that uses it:
<script setup lang="ts">
import { watch } from 'vue'
import { ElMessageBox } from "element-plus";
import { toasts } from '~/lib/toast'
watch(toasts, () => {
console.log("toasts changed")
while (toasts.value.length) {
const opts = toasts.value.pop()!
ElMessageBox(opts)
}
})
</script>
<template>
<span>I'm here</span>
</template>
The Toast component is added in App.vue. I can see that it is rendered (the "I'm here text is shown in the browser.)
When I call showSuccess("TEST")
from another component, then the following happens:
pushing {type: 'success', message: 'DOH'}
appears in the console logtoasts changed
is NOT SHOWN in the console log, and nothing else happensAFAIK watchers are deep by default ( see https://vuejs.org/guide/essentials/watchers.html#deep-watchers ), and the watcher function should be called when an item is pushed into the array.
What am I doing wrong?
The deep functionality is by default for objects only. This is something originally mentioned in the Vue 3 migration guide. Specific to arrays, "To trigger on mutation, the deep option must be specified."
watch(toasts, () => {
console.log("toasts changed")
while (toasts.value.length) {
const opts = toasts.value.pop()!
ElMessageBox(opts)
}
}, { deep: true })