Vue 3 无法清除超时

问题描述 投票:0回答:1

我正在学习 Vue 3 做一个记忆游戏。我有一个对象(卡片)代理数组,对象具有以下格式:

{
    "id": "01",
    "image": "01.jpg",
    "isFlipped": false
}
{
    "id": "07",
    "image": "01.jpg",
    "isFlipped": false
}

我的 flipCard méthodes turns card.isFlipped:true 显示图像。当显示 2 张牌时,将调用比较方法。如果有匹配卡,请不要打开。如果没有匹配卡,则在 setTimeOut 1.5 秒后再次取消翻转。 如果在 setTimeOut 的 1.5 秒之前翻转了另一辆车,我需要清除此超时以在打开下一张之前(在 1.5 秒之前)打开显示的 2 张卡片。我已经尝试了 2 个月。 谁能帮帮我,谢谢

我的组件

// flip 2 cards and compare them
function flipCard(card) {
  clearTimeout(timeoutId.value);
  card.isFlipped = true;
  clicksNumber.value += 1;
  comparedCards.value.push(card);

  if (comparedCards.value.length === 2) {
    compare(comparedCards.value[0], comparedCards.value[1]);
  }
}

let timeoutId = ref();
function unflip(card) {
  // Set a timeout and assign the ID to the timeoutId variable
  timeoutId.value = setTimeout(() => {
    card.isFlipped = false;
  }, 1500);
}
// compares 2 flipped cards
function compare(a, b) {
  if (a.image == b.image) {
    found.value.push(a, b);
    // remove found values from not found array
    notFound.value = notFound.value.filter(
      (item) => !found.value.includes(item)
    );

  } else {
    comparedCards.value.forEach((card) => {
      unflip(card); //unflips cards agter 1.5 secs
    });
  }
  comparedCards.value = [];
}

我尝试初始化总点击次数 以及每次我们有 2 张卡片进行比较时的点击次数 (stopClick)

 let clicksNumber = ref(0);
let stopClick = ref();

然后当达到 2 张卡片进行比较时,获得发生这种情况时的点击次数 并观察它与 totalClicks 的比较 如果这些不同,请调用 clearTimeout(timeoutId)

function flipCard(card) {
  clearTimeout(timeoutId.value);
  card.isFlipped = true;
  clicksNumber.value += 1;
  comparedCards.value.push(card);

  if (comparedCards.value.length === 2) {
    stopClick.value = clicksNumber.value;
    compare(comparedCards.value[0], comparedCards.value[1]);
  }
}

watch(clicksNumber, (stopClick) => {
  if (clicksNumber.value != stopClick) {
clearTimeout(timeoutId)
  }
});

还尝试了大约 20 种不同的东西,但都不起作用......:-(

我没有任何错误,只是在1.5秒之前点击我可以同时翻转3 4或5张牌

javascript vuejs3 settimeout vue-composition-api cleartimeout
1个回答
0
投票

因为

comparedCards
包含两个项目,你在这里设置两个超时:

    comparedCards.value.forEach((card) => {
      unflip(card);
    });

所以

timeoutId
将只包含最后一个超时ID。

要解决此问题,您可以将

timeoutId
设为数组,或更改
unflip()
以处理两张牌:

function unflip(cards){
  timeoutId.value = setTimeout(() => {
    cards.forEach(card.isFlipped = false);
  }, 1500);
}

顺便说一句。我不认为让

timeoutId
成为 ref 对你有多大帮助——你永远不会在模板中使用它。


第二个问题是你实际上不只是想取消超时。如果显示了两张不匹配的牌并且玩家翻转了另一张牌,您不只是想取消等待再次翻转前两张牌,而是想立即翻转它们:

let timeoutId = null; // <--- doesn't have to be a ref

function compare(a, b) {
  if (a.image == b.image) {
    ...
    comparedCards.value = []; // <--- cards match, remove right away
  } else {
    timeoutId = setTimeout(unflip, 1500); // <--- wait to unflip
  }
  // <--- do not clear compared cards here
}


function flipCard(card) {
  if(timeoutId){
    unflip() //<--- abort timeout, unflip right away
  }
  card.isFlipped = true;
  comparedCards.value.push(card);

  if (comparedCards.value.length === 2) {
    compare(...comparedCards.value);
  }
}

function unflip() {
  if(timeoutId){
    clearTimeout(timeoutId);
    timeoutId = null;
  }
  comparedCards.value.forEach(card => card.isFlipped = false); // unflip all opened cards
  comparedCards.value = [] // no more open cards
}

我可能会将

comparedCards
重命名为
unflippedCards
或其他名称。

© www.soinside.com 2019 - 2024. All rights reserved.