如何解决在 Svelte Store 中使用 Throttle
我正在尝试 throttle 在 Svelte 中执行一个函数。但是,在自动订阅中使用油门似乎会破坏它。考虑以下示例 (REPL):
<script>
import throttle from 'lodash.throttle';
import { writable } from 'svelte/store';
const arr = writable(['A','B','C']);
function foo(val) {
console.log('foo: ',val);
}
</script>
{#each $arr as a}
<button on:click={throttle(() => { foo(a); },1000)}>
Button {a}
</button>
{/each}
foo(a)
的执行根本没有受到限制。如果您移除 {#each $arr as a}
块并仅将字符串传递给 foo,您会看到它按预期工作。
我假设这与事件循环以及 Svelte 自动订阅的工作方式有关,但不知道确切原因。想知道是否有人知道 a) 为什么会发生这种情况以及 b) 可能的解决方案是什么样的?
解决方法
如果您查看 Svelte 为此生成的代码,您会发现当您传递存储值时,它会在每次点击时重新生成节流函数。这会在每次点击时重置油门计时器。
dispose = listen(button,"click",function () {
if (is_function(throttle(click_handler,1000)))
throttle(click_handler,1000).apply(this,arguments);
});
无论出于何种原因,当您传递常规字符串时都不会发生这种情况。
dispose = listen(button,throttle(click_handler,1000));
这可能是 Svelte 中的一个错误,但我不确定。可能值得在 GitHub repo 上提出问题。
我能够通过提前生成节流函数来解决这个问题:
<script>
import throttle from 'lodash.throttle';
import { writable } from 'svelte/store';
const arr = writable(['A','B','C']);
function foo(val) {
console.log('foo: ',val);
}
$: throttledFns = $arr.map(val => getThrottled(val));
function getThrottled(val) {
console.log('getting throttled');
return throttle(() => { foo(val); },1000);
}
</script>
{#each $arr as a,idx}
<button on:click={throttledFns[idx]}>
Button {a}
</button>
{/each}
这将在 store 数组更改时重新生成受限制的函数,但不会在每次点击时重新生成。
您也可以生成一个限制版本的 foo 并使用它,但这会限制对按钮的所有点击(例如,如果您点击 A 然后点击 B,点击 B 将被限制)。
<script>
// as before
const throttledFoo = throttle(foo,1000);
</script>
{#each $arr as a,idx}
<button on:click={() => throttledFoo(a)},1000)}>
Button {a}
</button>
{/each}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。