想在 vuejs 中使用 vuetify 小吃吧作为全局自定义组件

Posted

技术标签:

【中文标题】想在 vuejs 中使用 vuetify 小吃吧作为全局自定义组件【英文标题】:want to use vuetify snackbar as a global custom component in vuejs 【发布时间】:2020-10-29 14:31:33 【问题描述】:

我使用snackbar 在vuejs 中显示成功消息。我想做一个全局自定义的snackbar组件。

<template>
  <div name="snackbars">
    <v-snackbar
      v-model="snackbar"
      :color="color"
      :timeout="timeout"
      :top="'top'"
    >
       text 

      <template v-slot:action=" attrs ">
        <v-btn dark text v-bind="attrs" @click="snackbar = false">
          Close
        </v-btn>
      </template>
    </v-snackbar>
  </div>
</template>

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

然后我将它作为一个组件导入到我的每个表单中。

<SnackBar :snackbar="snackbar" :color="color" :text="text" />

但我的问题是我不能在我的子组件中使用snackbar 作为道具。它显示了这个错误。

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "snackbar" 

我该如何解决这个问题。谁能帮帮我?

【问题讨论】:

您的错误状态不在道具上使用 v-model。只需使用计算代理它并向父​​级发送更新 【参考方案1】:

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

【讨论】:

我认为您可以删除动作部分并直接在突变中执行,因为您没有任何副作用。【参考方案2】:

我意识到这已经过时了,但感谢 google,我将添加我的解决方案。 我使用它,因为我没有看到将 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!')

【讨论】:

非常有用,干净又简单!谢谢! 嗨,我使用了你的方法,但它显示错误(this.$root.vtoast.show())【参考方案3】:

另一种解决方案是使用带有 getter 和 setter 的计算值。

使用选项 api

<template>
  <v-snackbar v-model="show" :color="color">
     message 
    <template v-slot:action=" attrs ">
      <v-btn text v-bind="attrs" @click="show = false">Close</v-btn>
    </template>
  </v-snackbar>
</template>

<script>
import  mapGetters  from 'vuex';

export default 
  computed: 
    ...mapGetters(
      message: 'snackbar/message',
      color: 'snackbar/color'
    ),
    show: 
      get() 
        return this.$store.state.snackbar.show
      ,
      set(v) 
        this.$store.commit('snackbar/SET_SHOW', v)
      
    
  

</script>

使用合成 api 插件

<template>
  <v-snackbar v-model="show" :color="color">
     message 
    <template v-slot:action=" attrs ">
      <v-btn text v-bind="attrs" @click="show = false">Close</v-btn>
    </template>
  </v-snackbar>
</template>

<script>
import  defineComponent, computed  from '@vue/composition-api';

export default defineComponent(
  setup(_props,  root ) 
    const show = computed(
      get: () => root.$store.state.snackbar.show,
      set: (v) => root.$store.commit('snackbar/SET_SHOW', v),
    );
    const message = computed(() => root.$store.state.snackbar.message);
    const color = computed(() => root.$store.state.snackbar.color);

    return 
      show,
      message,
      color,
    ;
  ,
);
</script>

在这里使用可组合的更好的实现https://gist.github.com/wobsoriano/2f3f0480f24298e150be0c13f93bac20

【讨论】:

【参考方案4】:

你有一个道具和数据相同。

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>

【讨论】:

抱歉,这是我的错。我已经删除它但发生同样的错误 @KalanaMihiranga 您能否在代码框中为您提供该问题的代码,因为我无法重现该问题?

以上是关于想在 vuejs 中使用 vuetify 小吃吧作为全局自定义组件的主要内容,如果未能解决你的问题,请参考以下文章

Vuejs Vuetify 如何在 v-select 中访问对象的属性

VueJs - Vuetify - v-navigation-drawer 与智能手机的迷你变体

如何在带有 vuetify 和 vuex 的 Vuejs 项目中使用 Jest?节点模块和 Vuetify 问题

Vuejs & Vuetify - 在对话框中使用 Tinymce 作为组件需要重新加载

POST 和 PUT 请求中的问题,使用 axios、vuetify 数据表、vuejs

VueJS + Vuex + Vuetify 导航抽屉