我想使用
querySelector()
,但我发现 Svelte 有另一种方法可以做到这一点。
通过使用
bind:this
问题是有时它可以工作,但大多数时候它永远不会工作
通过输出
undefined
<script>
let thisDiv;
console.log(thisDiv) // ❌ "undefined" ✅ "<div>"
</script>
<div bind:this={thisDiv}>hello world</div>
但真正的问题在这里
因为我现在不需要
console.log
我之前写的东西只是为了让你了解这个bug
这样我就可以开始提供更多信息。
因为我有一个使用该变量的函数
并在事件“
on:animationend
”开始时调用该函数。
像这样:
<div
bind:this={thisDiv}
on:animationend={doStuff()}
></div>
问题是
animationend
仍然在 console.log thisDiv
undefined
是的,好的...
但是CSS中的动画只有50毫秒长。还尝试过 0.5s
CSS 不会阻止 javascript,因此当 CSS 执行动画时,js 将继续工作(据我所知)
和 0.5 秒,我认为对于做一个简单的
bind:this
(querySelector) 来说已经很多了
这怎么可能?半秒后就得到了一个正常的querySelector,但仍然什么也没有。
这里是 REPL 在线 svelte 源代码示例:
https://svelte.dev/repl/b49d019ce7f8426b80295158b091520f?version=3.50.1
确保取消 child.svelte 中第 9 行的注释
...或者直接看这个
App.svelte
<script>
import Child from "./Child.svelte"
function generateExample() {
let output = [];
for(let i=0; i<=100; i++) {
output = [
...output, `text ${i}`
]
}
return output;
}
let array = generateExample()
</script>
{#each array as item, index}
<Child {index}>
{item}
</Child>
{/each}
儿童苗条
<script>
export let index;
const DELAY = 50;
let thisDiv;
// UNCOMMENT THE NEXT LINE
function doStuff() {
// thisDiv.scrollIntoView();
}
</script>
<div
style="--delay:{index * DELAY}ms;"
bind:this={thisDiv}
on:animationend={doStuff()}
>
<slot></slot>
</div>
<style>
div {
animation: show var(--delay);
}
@keyframes show {
from {
translate: 100vw;
}
to {
translate: 0;
}
}
</style>
解决方案代码:
<script>
// other your code
$: if(thisDiv) {
thisDiv.addEventListener("animationend", () => {
thisDiv.scrollIntoView()
})
}
</script>
并且由于
if
检查和本机 JavaScript 代码,也没有错误。
发生错误是因为当您编写
bind:this
时,该值无法直接获得(但这并不意味着速度很慢)
那么如何解决呢?
我相信
$: if(thisDiv)
应该能够成功。
所以将所有逻辑放入
IF
这也意味着您不需要再使用属性
on:animationend
,因为它不在 IF
内
所以我们颠倒了逻辑,
我现在看到@H.B建议了一种更简单的方法,因为你的错误只是拼写错误
❌
doStuff()
✅doStuff
问题是
animationend
尝试仅记录索引/时间:
function doStuff() {
console.log(index, 'end', new Date());
}
建议在
onMount
(来自'svelte'
)中添加事件侦听器,并在销毁时再次清理它:
onMount(() => {
thisDiv.addEventListener('animationend', doStuff);
() => thisDiv.removeEventListener('animationend', doStuff);
})