Javascript VUE 3-使用setInterval从阵列中删除项

Javascript VUE 3-使用setInterval从阵列中删除项,javascript,vue.js,vuejs3,Javascript,Vue.js,Vuejs3,我想用VUE3创建一个简单的Snackbar。我已经在VUE2中完成了这项工作,但Vue3的工作方式似乎略有不同 我已将邮件数组保存在商店中,如下所示: import { createStore } from 'vuex' export default createStore({ state: { snackbarText: [] }, mutations: { DELETE_SNACKBAR_MESSAGE(state) { state.snackba

我想用VUE3创建一个简单的Snackbar。我已经在VUE2中完成了这项工作,但Vue3的工作方式似乎略有不同

我已将邮件数组保存在商店中,如下所示:

import { createStore } from 'vuex'

export default createStore({
  state: {
    snackbarText: []
  },
  mutations: {
    DELETE_SNACKBAR_MESSAGE(state) {
      state.snackbarBarText.shift()
    },
    ADD_SNACKBAR_MESSAGE(state, message) {
      state.snackbarBarText.push(message)
    }
  },
  getters: {
    MESSAGES: (state) => state.snackbarText
  }
})

这就是我到目前为止在Snackbar.vue组件中所做的:

import { useStore } from 'vuex';
import { ref, watch} from 'vue';

export default {
  set() {
    const store = useStore();
    const text = ref(store.getters["MESSAGES"]);
    
    if (text.value.length) {
      let timer = setInterval(() => {
        store.commit('DELETE_SNACKBAR_MESSAGE');
        
        if (text.value.length) {
          clearInterval(timer)
        }
      }, 3000)
    }    

    return { text }
  }
}
有没有办法检查Snackbar中
文本的长度
ref并调用启动计时器的函数?我只是在Vue3中实现这一点有困难,因为我还不太熟悉合成API

它的工作方式是,将消息添加到数组中并显示给用户。3秒后,它们将从阵列中移除。使用
watch
很笨重,在setInterval停止后,我很难重新启动它


谢谢大家!

!重写我使用
setInterval
的原始答案。 setInterval不适用于此特定类型的功能。不能以“干净”的方式从一个元素转换到下一个元素

在Vue2中,您可能会使用
EventBus
来侦听snackbar消息数组的任何更改。但是在Vue3中,他们删除了该功能。您可以继续使用类似EventBus的模块或使用

这是整个组件:

<template>
  <transition name="component-fade" @after-leave="checkForMoreSnacks">
    <div class="snackbar" v-if="currentSnack">
      <div class="snackbar__container">
        <p>{{ currentSnack }}</p>
        <button @click="closeCurrentSnack">Close Me</button>
      </div>
    </div>
  </transition>
</template>

<script>
import { useStore } from "vuex";
import { computed, ref } from "vue";
export default {
  setup() {
    const timerInterval = 1500;
    const store = useStore();
    let timeoutToken = null;
    let snacks = computed(() => store.getters["GET_SNACKBAR_MESSAGES"]);
    let currentSnack = ref(null);

    // The event that triggers the Snackbar to initially appear.
    // Much like an EventBus emit
    store.subscribe(mutation => {
      // listen for this specific mutation call
      if (mutation.type === "ADD_SNACKBAR_MESSAGE") {
        // if there is already a currentSnack don't proceed
        if (currentSnack.value) return;

        // if no token, set the value to this settimeout function where we do:
        // 1. Set the current value to the [0] index of the snacks array.
        // 2. Remove that item from the snacks array in the store
        currentSnack.value = snacks.value[0];
        timeoutToken = setTimeout(() => {
          closeCurrentSnack();
        }, timerInterval);
      }
    });

    function closeCurrentSnack() {
      store.commit("DELETE_SNACKBAR_MESSAGE");
      currentSnack.value = null;
      timeoutToken = null;
    }

    function checkForMoreSnacks() {
      if (!snacks.value.length) {
        timeoutToken = null;
        currentSnack.value = null;
      } else {
        currentSnack.value = snacks.value[0];
        timeoutToken = setTimeout(() => {
          closeCurrentSnack();
        }, timerInterval);
      }
    }

    return {
      currentSnack,
      checkForMoreSnacks,
      closeCurrentSnack
    };
  }
};
</script>

<style lang="scss" scoped>
.snackbar {
  position: absolute;
  right: 10px;
  bottom: 10px;
  max-width: 500px;
  border: solid 2px red;
  padding: 1rem;
  border-radius: 5px;

  &__container {
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: 1fr 30px;
  }
}

.component-fade-enter-active,
.component-fade-leave-active {
  transition: opacity 0.3s ease;
}

.component-fade-enter-from,
.component-fade-leave-to {
  opacity: 0;
}
</style>

{{CurrentSnapshot}}

关上我 从“vuex”导入{useStore}; 从“vue”导入{computed,ref}; 导出默认值{ 设置(){ 常数timerInterval=1500; const store=useStore(); 让timeoutToken=null; 让零食=计算(()=>store.getters[“获取SNACKBAR\u消息]); 设CurrentSnapshot=ref(null); //触发Snackbar最初出现的事件。 //很像事件总线 store.subscribe(变异=>{ //听这个特定的突变呼叫 if(mutation.type==“添加\u SNACKBAR\u消息”){ //如果已经存在一个问题,请不要继续 if(currentSnapshot.value)返回; //如果没有令牌,请将该值设置为此settimeout函数,我们将执行以下操作: //1.将当前值设置为数组的[0]索引。 //2.将该物品从商店的零食阵列中移除 currentSnack.value=snacks.value[0]; timeoutToken=setTimeout(()=>{ CloseCurrentSnapshot(); },timerInterval); } }); 函数closeCurrentSnapshot(){ 提交(“删除SNACKBAR\u消息”); currentSnapshot.value=null; timeoutToken=null; } 函数CHECKFORMORE(){ 如果(!零食.值.长度){ timeoutToken=null; currentSnapshot.value=null; }否则{ currentSnack.value=snacks.value[0]; timeoutToken=setTimeout(()=>{ CloseCurrentSnapshot(); },timerInterval); } } 返回{ 小吃, checkformore零食, 快餐 }; } }; .斯纳克巴{ 位置:绝对位置; 右:10px; 底部:10px; 最大宽度:500px; 边框:实心2px红色; 填充:1rem; 边界半径:5px; &__容器{ 显示:网格; 网格模板列:1fr; 网格模板行:1fr 30px; } } .组件淡入激活状态, .组件淡入淡出激活状态{ 过渡:不透明度0.3s; } .组件淡入淡出, .组件淡出至{ 不透明度:0; }
关键在于离开后的
@钩子。我意识到,一旦显示的snackbar被移除,我们就可以使用这个钩子检查更多

这个钩子也是不使用
setInterval
的原因

还为此创建了一个git