我意识到这已经过时了,但是感谢谷歌,我将添加我的解决方案。 我使用这个,因为我不明白使用 vuex 作为小吃店有什么意义。这比需要的工作还要多。
创建一个名为vtoast的vue组件
<template>
<v-snackbar
:color="color"
:timeout="timer"
v-model="showSnackbar"
bottom
right
>
<v-icon left>{{icon}}</v-icon>{{message}}
</v-snackbar>
</template>
<script>
export default {
name: "vtoast",
data() {
return{
showSnackbar: false,
message: '',
color: 'success',
icon: 'mdi-check',
timer: 3000
}
},
methods:{
show(data) {
this.message = data.message || 'missing "message".'
this.color = data.color || 'success'
this.timer = data.timer || 3000
this.icon = data.icon || 'mdi-check'
this.showSnackbar = true
}
}
}
</script>
在主应用程序根目录的某个位置,添加以下内容。(我通常将其放在 App.vue 中)
<template>
...
<!-- toast -->
<vtoast ref="vtoast"/>
...
</template>
<script>
import vtoast from '@/your/vtoast/directory/vtoast'
export default{
name: 'App', //or whatever your root is
components:{
vtoast
},
mounted() {
this.$root.vtoast = this.$refs.vtoast
},
}
</script>
并像这样访问它...
this.$root.vtoast.show()
this.$root.vtoast.show({message: 'Ahoy there!'})
我找到了一种使用 vuex 修复我的解决方案的方法。
<template>
<div name="snackbars">
<v-snackbar v-model="show" :color="color" :timeout="timeout" :top="'top'">
{{ text }}
<template v-slot:action="{ attrs }">
<v-btn dark text v-bind="attrs" @click="show = false">
Close
</v-btn>
</template>
</v-snackbar>
</div>
</template>
<script>
export default {
created() {
this.$store.subscribe((mutation, state) => {
if (mutation.type === "snackbar/SHOW_MESSAGE") {
this.text = state.snackbar.text;
this.color = state.snackbar.color;
this.timeout = state.snackbar.timeout;
this.show = true;
}
});
},
data() {
return {
show: false,
color: "",
text: "",
timeout: 0,
};
},
};
</script>
在我的 vuex 模块中我是这样写的
export default {
namespaced: true,
state: {
text: "",
color: "",
timeout: "",
},
mutations: {
SHOW_MESSAGE(state, payload) {
state.text = payload.text;
state.color = payload.color;
state.timeout = payload.timeout;
},
},
actions: {
showSnack({ commit }, payload) {
commit("SHOW_MESSAGE", payload);
},
},
};
然后我将 Snackbar 子组件导入到我的父组件中并像这样发送数据。
...mapActions("snackbar", ["showSnack"]),
saveDetails() {
this.showSnack({
text: "Successfully Saved!",
color: "success",
timeout: 3500,
});
}
您可以使用 Vue 内置的 Provide/Inject API,并创建一个提供小吃栏数据的高阶组件:
<script setup>
import { computed, provide, ref } from 'vue';
const show = ref(false)
const message = ref('')
const color = ref('')
provide('snackbar', {
show(options) {
message.value = options.message
color.value = options.color
show.value = true
},
hide() {
show.value = false
}
})
</script>
<template>
<slot />
<v-snackbar v-model="show" :color="color">
{{ message }}
<template #actions>
<v-btn variant="text" @click="show = false">Close</v-btn>
</template>
</v-snackbar>
</template>
App.vue
内容<script setup lang="ts">
import SnackbarProvider from './components/SnackbarProvider.vue'
</script>
<template>
<v-app>
<SnackbarProvider>
<v-main>
<!-- Other -->
</v-main>
</SnackbarProvider>
</v-app>
</template>
<script setup>
import { inject } from 'vue';
const { show } = inject('snackbar')
</script>
<template>
<v-btn @click="show({ message: 'Hello', color: 'success' })">
Show
</v-btn>
</template>
您还可以使用我的模块轻松创建对话框和小吃栏:
你有一个 prop 和数据中的相同。
从
data()
中删除小吃栏,因为它可以从 prop
中获得。
<script>
export default {
props: {
snackbar: {
type: Boolean,
required: true,
},
color: {
type: String,
required: false,
default: "success",
},
timeout: {
type: Number,
required: false,
default: 3000,
},
text: {
type: String,
required: true,
},
}
};
</script>
这就是我使用 Options API 所做的,仅使用道具和事件;
这是
Snackbar.vue
组件
<template>
<div class="text-center">
<v-snackbar
transition="true"
bottom
right
v-model="show"
:color="snackbar.color"
:timeout="snackbar.timeout"
class="snackbar-shadow"
>
<div class="d-flex align-start alert-notify">
<v-icon size="24" class="text-white mr-5">{{ snackbar.icon }}</v-icon>
<p class="mb-0">
<span class="font-size-root font-weight-600">{{
snackbar.title
}}</span>
<br />
{{ snackbar.message }}
</p>
</div>
<template v-slot:action="{ attrs }">
<v-btn
icon
elevation="0"
max-width="136"
:ripple="false"
height="43"
class="font-weight-600 text-capitalize py-3 px-6 rounded-sm"
color="rgba(255,255,255, .85)"
text
v-bind="attrs"
@click="show = false"
>
<v-icon size="13">fas fa-times</v-icon>
</v-btn>
</template>
</v-snackbar>
</div>
</template>
<script>
export default {
name: "snackbar",
props: {
snackbar: Object,
},
computed: {
show: {
get() {
return this.snackbar.visible;
},
set(value) {
this.$emit("closeSnackbar", value);
},
},
},
};
</script>
这是
App.vue
组件
<template>
<!-- Snackbar -->
<snackbar :snackbar="snackbar" @closeSnackbar="SnackbarClose"></snackbar>
</template>
<script>
export default {
name: "app",
data() {
return {
snackbar: {
visible: false,
timeout: 2000,
color: "#11cdef",
title: "Hello",
message: null,
icon: "fas fa-bell",
},
};
},
created: { this.SnackbarShow(); }
methods: {
SnackbarShow() {
this.snackbar.visible = true;
this.snackbar.message = "Hola!👋 I'm a snackbar";
},
SnackbarClose() {
this.snackbar.visible = false;
},
},
};
</script>