繁体   English   中英

Svelte:动态语句中的代码不会更新组件

[英]Svelte : code in dynamic statement doesn't update components

我有三个组件:应用程序、键盘和键。

键盘组件基于具有以下结构的变量“keys”加载多个 Key 组件: { char: string, isPressed: boolean }[] Key 组件有一个 boolean pressed的道具,用于造型。

我希望能够从 App 组件中重置所有这些isPressed属性,并在按下某些键时相应地更新视图。 使用 Vue.js 我可能使用了全局事件,这里我尝试使用绑定道具和动态语句。 所以我在键盘组件中有一个动态语句,它在我想要的时候执行,但只有在你按下另一个键之前才有效。 有趣的是,当我使用“清除”按钮时它工作正常。

我在这里做了一个repl: https://svelte.dev/repl/b7c11d9f0e494195884be0994387ba4c?version=3.35.0

应用程序

<main>
  <Keyboard on:pressed-change="{checkKeys}"
            bind:clear={clear} />
</main>

<script>
import Keyboard from './Keyboard.svelte';

let clear = false;
const text = 'AC'; 

function checkKeys({ detail: keys }) {
    console.log('check keys')
  if (keys.sort().join('') === text) {
        console.log('clear')
    clear = true;
  }
}
</script>

键盘

<main>
  <div>
    <section class="keys">
      {#each keys as { char, isPressed }, i}
        <Key char="{char}"
             bind:pressed={isPressed}
             on:key-press={handleKeyPress} />
      {/each}
    </section>

    <section>
      { pressed.join(' | ') }
    </section>
    <button on:click={clearKeyboard}>
      clear
    </button>
  </div>
</main>

<script>
import { createEventDispatcher } from 'svelte';
import Key from './Key.svelte';

export let clear;
let pressed = [];

const dispatch = createEventDispatcher();
    
let keys = [
    { char: "A", isPressed: false },
  { char: "B", isPressed: false },
  { char: "C", isPressed: false },
  { char: "D", isPressed: false },
  { char: "E", isPressed: false },
  { char: "F", isPressed: false },
  { char: "G", isPressed: false },
];

function handleKeyPress({ detail: char }) {
  const keyIndex = pressed.indexOf(char)
  if (keyIndex >= 0) {
    const tempArr = [...pressed];
    tempArr.splice(keyIndex, 1);
    pressed = tempArr;
    return;
  }
  pressed = [...pressed, char];
}

function clearKeyboard() {
  console.log('clear keyboard');
  keys = keys.map(key => ({ ...key, isPressed: false }));
  pressed = [];
}

$: if (clear) {
  clearKeyboard()
  clear = false;
}
$: dispatch('pressed-change', pressed);
</script>

钥匙

<div class="key"
     class:pressed
     on:click="{ press }">
  { char }
</div>

<script>
import { createEventDispatcher } from 'svelte';

export let char;
export let pressed;

const dispatch = createEventDispatcher();

function press() {
  pressed = !pressed;
  dispatch('key-press', char);
}
</script>

谢谢您的帮助。

您遇到的问题是由某处的某些竞争条件引起的。

Svelte 并不完全“即时”更新 DOM,而是分批安排更改。 您的代码中发生的情况是设置要按下的键的代码与“取消设置”它的类似信号冲突。

您可以使用await tick()告诉 Svelte 显式等待,直到应用当前计划的更改之后(tick 是 Svelte 渲染到 DOM 的时间)

import { tick } from 'svelte'

async function clearKeyboard() {
  await tick()
  console.log('clear keyboard');
  keys = keys.map(key => ({ ...key, isPressed: false }));
  pressed = [];
}

在上面的代码中,首先将应用当前更改,然后将键全部设置为 false。

如果您在混合中添加延迟,您可以通过在await tick()之后添加以下行来可视化正在发生的情况

await new Promise(res => setTimeout(res, 2000)) // will pause execution for two seconds

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM