请看一下这段代码:
const highlight = (element) => {
element.classList.remove('highlight');
setTimeout(() => {
element.classList.add('highlight');
}, 0);
element.onanimationend = () => {
element.classList.remove('highlight');
}
}
document.querySelector('body').addEventListener('click', event => {
if (event.target.hash) {
event.preventDefault();
const element = document.querySelector(event.target.hash);
highlight(element);
}
});
@keyframes highlight {
from {
background: red;
}
to {
background: white;
}
}
.highlight {
animation: highlight 5s;
}
<ul>
<li>
<a href="#foo">Foo</a>
<div>
<ul>
<li>
<a href="#foo-1">Foo 1</a>
</li>
<li>
<a href="#foo-2">Foo 2</a>
</li>
<li>
<a href="#foo-3">Foo 3</a>
</li>
</ul>
</div>
</li>
<li>
<a href="#bar">Bar</a>
</li>
<li>
<a href="#baz">Baz</a>
</li>
</ul>
<hr>
<div id="foo">
<h2>Foo</h2>
<ul>
<li id="foo-1">Foo 1</li>
<li id="foo-2">Foo 2</li>
<li id="foo-3">Foo 3</li>
</ul>
</div>
<div id="bar">
<h2>Bar</h2>
</div>
<div id="baz">
<h2>Baz</h2>
</div>
然后请运行代码片段(最好在整页上)并尝试:
点击“Foo”,等待一两秒,点击“Foo 1”,再等待一秒,点击“Foo 2”,等待一秒,再次点击“Foo 2”,等待一秒,点击“富 3 英寸。一切都按预期进行。
现在点击“Foo 1”(或“Foo 2”或“Foo 3”),等待3秒,然后点击“Foo”。如您所见,“Foo”的背景色动画与“Foo 1”(或“Foo 2”或“Foo 3”)的背景色动画同时结束。也可以说 CSS 类“highlight”从“Foo”中删除得太早了。
这是为什么以及如何解决这个问题?
问题是因为
animationend
事件正在 DOM 上传播。这意味着,如果动画在父级 li
之前在子级 div
上结束,则该事件将从 li
向上遍历 DOM,并被 div
上的事件处理程序捕获,同时还会删除 .highlight
在那里上课。
要解决此问题,请在
stopPropagation()
处理程序中对事件调用 animationend
:
const highlight = (element) => {
element.classList.remove('highlight');
setTimeout(() => {
element.classList.add('highlight');
}, 0);
element.onanimationend = e => {
e.stopPropagation();
element.classList.remove('highlight');
}
}
document.querySelector('body').addEventListener('click', event => {
if (event.target.hash) {
event.preventDefault();
const element = document.querySelector(event.target.hash);
highlight(element);
}
});
@keyframes highlight {
from {
background: red;
}
to {
background: white;
}
}
.highlight {
animation: highlight 5s;
}
<ul>
<li>
<a href="#foo">Foo</a>
<div>
<ul>
<li><a href="#foo-1">Foo 1</a></li>
<li><a href="#foo-2">Foo 2</a></li>
<li><a href="#foo-3">Foo 3</a></li>
</ul>
</div>
</li>
<li><a href="#bar">Bar</a></li>
<li><a href="#baz">Baz</a></li>
</ul>
<hr>
<div id="foo">
<h2>Foo</h2>
<ul>
<li id="foo-1">Foo 1</li>
<li id="foo-2">Foo 2</li>
<li id="foo-3">Foo 3</li>
</ul>
</div>
<div id="bar">
<h2>Bar</h2>
</div>
<div id="baz">
<h2>Baz</h2>
</div>