【问题标题】:Transitionend event and eventloop [duplicate]Transitionend事件和事件循环[重复]
【发布时间】:2021-11-03 01:47:07
【问题描述】:

解释我的问题的最好方法是以下两个演示:

他们就是这样:

演示 1(在 chrome 中按预期工作,在 Firefox 中不起作用)

let handler = function () {
    block.classList.add("visible");
    requestAnimationFrame(() => block.classList.add("move"));
    block.addEventListener(
        "transitionend",
        () => {
            console.log("style is removed");
            this.addEventListener("click", handler, { once: true });
            block.classList.remove("move");
        },
        { once: true }
    );
};
btn.addEventListener("click", handler, { once: true });
.main {
    display: none;
    width: 100px;
    height: 100px;
    background: red;
    transition: all 5.5s ease;
}
.visible {
    display: block;
}
.move {
    transform: translateX(100px);
    background: blue;
}
<div id="block" class="main"></div>
<button id="btn">Animate</button>

演示 2(工作不正确)

let handler = function () {
    block.classList.add("visible");
    block.classList.add("move");
    block.addEventListener(
        "transitionend",
        () => {
            console.log("style is removed");
            this.addEventListener("click", handler, { once: true });
            block.classList.remove("move");
        },
        { once: true }
    );
};
btn.addEventListener("click", handler, { once: true });
.main {
    display: none;
    width: 100px;
    height: 100px;
    background: red;
    transition: all 5.5s ease;
}
.visible {
    display: block;
}
.move {
    transform: translateX(100px);
    background: blue;
}
<div id="block" class="main"></div>
<button id="btn">Animate</button>

我将快速强调两个演示之间的区别:

  1. 第一个演示有 requestAnimationFrame

  1. &lt;div&gt; 块在第一个演示中启动点击处理程序之前具有“可见”类
  2. 在点击处理程序中,它有在第二个演示中添加“可见”类的代码

所以主要问题是:为什么第二个演示没有触发 transitionend 事件以及为什么我看不到转换?


额外演示

let handler = function () {
    alert(1);
    block.classList.add("visible");
    alert(2);
    setTimeout(() => {
      alert(4);
      block.classList.add("move");
      alert(5);
    });
    block.addEventListener(
        "transitionend",
        () => {
            console.log("style is removed");
            this.addEventListener("click", handler, { once: true });
            block.classList.remove("move");
        },
        { once: true }
    );
    alert(3);
};
btn.addEventListener("click", handler, { once: true });
.main {
    display: none;
    width: 100px;
    height: 100px;
    background: red;
    transition: all 5.5s ease;
}
.visible {
    display: block;
}
.move {
    transform: translateX(100px);
    background: blue;
}
<div id="block" class="main"></div>
<button id="btn">Animate</button>

在 chrome 和 firefox 中检查它,似乎代码的某些部分调用了重新绘制,如果不是,请纠正我并解释原因。

【问题讨论】:

    标签: javascript dom-events event-loop


    【解决方案1】:

    这里有几件事,你首先写了block.classList.add("visible");,我认为主要原因是你故意错过了这个class="main visible",就像你在代码中写的class="main"一样。

    您实际上需要使用 css 样式技术,即使用 none 隐藏 div 并使用 block 显示它。这是我首先隐藏它.visible { display: none; } 然后显示它我使用document.getElementById("block").style.display = "block"; 所做的。我添加了一个小延迟,让它有时间完成显示,然后开始制作动画,如果你移除延迟,它会起作用但不起作用。

    let handler = function () {
            //block.classList.add("visible");
    document.getElementById("block").style.display = "block"; 
    setTimeout(() => { block.classList.add("move"); }, 300);
            //block.classList.add("move");
    
        block.addEventListener(
            "transitionend",
            () => {
                console.log("style is removed");
                this.addEventListener("click", handler, { once: true });
                block.classList.remove("move");
            },
            { once: true }
        );
        };
        btn.addEventListener("click", handler, { once: true });
     .main {
            display: none;
            width: 100px;
            height: 100px;
            background: red;
            transition: all 5.5s ease;
        }
        .visible {
            display: none;
        }
        .move {
            transform: translateX(100px);
            background: blue;
        }
        <div id="block" class="main visible"></div>
        <button id="btn">Animate</button>

    所以要回答为什么它没有触发,这是由于我在上面解释的原因。

    【讨论】:

    • 嗯,这是一个不错的尝试,但我没想到会像你这样回答。你读过我的主要问题吗?这很重要。如果你能解释一下,我会很高兴听到你的声音。
    • 您的第二个演示直接跳到蓝色,因为您的 div 在点击期间不可见,而在另一边您试图添加而不是显示它(将 div 呈现给视图)。请在代码 sn-p 上重新运行您的第二个演示,您将看到它运行此 CSS 代码 .move { transform: translateX(100px); background: blue; } 只是因为 block.classList.add("visible"); 在这里不起作用,事实上 block.classList.add("visible"); 是错误的方法
    • 好吧,再次检查我的第一个示例,并尝试回答它为什么有效(我已经重写了它)
    • 现在您的演示都没有按预期工作。为什么?你在你的 div 类中删除可见。正如我所说,您应该使用 CSS 样式方法来显示或隐藏 div,而不是您的操作方式。将class="main visible" 放在你的 div 类中它会起作用。
    • 第一个演示仍然按预期工作,我可以看到过渡。为什么你说它不起作用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 2013-09-12
    • 2012-05-27
    • 2018-03-04
    • 2015-10-13
    • 1970-01-01
    相关资源
    最近更新 更多