想使用vuetify Snackbar作为vuejs中的全局自定义组件

问题描述 投票:0回答:5
vue.js vuetify.js
5个回答
18
投票

我意识到这已经过时了,但是感谢谷歌,我将添加我的解决方案。 我使用这个,因为我不明白使用 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!'})

11
投票

我找到了一种使用 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,
          });
     }

3
投票

您可以使用 Vue 内置的 Provide/Inject API,并创建一个提供小吃栏数据的高阶组件:

  1. 创建提供商
<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>
  1. 使用 Provider 包装您的
    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>
  1. 在提供者内部的任何地方使用提供的数据:
<script setup>
import { inject } from 'vue';

const { show } = inject('snackbar')
</script>

<template>
  <v-btn @click="show({ message: 'Hello', color: 'success' })">
    Show
  </v-btn>
</template>

您还可以使用我的模块轻松创建对话框和小吃栏:


0
投票

你有一个 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>

0
投票

这就是我使用 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>
© www.soinside.com 2019 - 2024. All rights reserved.