JavaScript追加DOM子元素(“appendChild”方法)后如何执行代码?

问题描述 投票:0回答:1

我已经检查了主题JavascriptappendChild回调?。在那里,目标元素是

video
,因此使用 loadedmetadata 是这种情况的解决方案。

就我而言,有小吃店,但它只是一个

div

我预计下面的代码会将小吃栏附加到

body
,然后将CSS类
Snackbar-Transition__HiddenState
替换为
Snackbar-Transition__DisplayingState
,这将触发CSS转换。

document.querySelector("body").appendChild(snackbar);
snackbar.style.transitionDuration = `${ displayingDuration__seconds }s`;
snackbar.classList.remove("Snackbar-Transition__HiddenState");
snackbar.classList.add("Snackbar-Transition__DisplayingState");

与预期相反,转变是即时的:

enter image description here

但是,如果我们在

appendChild
之后添加延迟,过渡将会很平滑:

document.querySelector("body").appendChild(snackbar);

setTimeout(
  () => {
    snackbar.style.transitionDuration = `${ displayingDuration__seconds }s`;
    snackbar.classList.remove("Snackbar-Transition__HiddenState");
    snackbar.classList.add("Snackbar-Transition__DisplayingState");
  },
  500
);

enter image description here

这不是解决方案,因为我们不知道延迟必须是多少。 大延迟会让人感觉应用程序滞后,而小延迟(几毫秒)可能还不够。这是当需要回调

appendChild
但没有这样的回调时的情况。可以用什么代替?

javascript dom
1个回答
0
投票

发生的情况是浏览器在宏任务完成后重新渲染页面(JS 在某个事件后结束工作)。

document.querySelector("body").appendChild(snackbar);
snackbar.style.transitionDuration = `${ displayingDuration__seconds }s`;
snackbar.classList.remove("Snackbar-Transition__HiddenState");
snackbar.classList.add("Snackbar-Transition__DisplayingState");

您在这里所做的是添加元素,更改其类,因此当您完成后,浏览器会看到一个新添加的元素,就是这样,浏览器不知道该元素之前的状态,因此无法推断出任何转换。

当您将

setTimeout
添加到等式中时,您允许浏览器捕获 CSS 类更改。你可以把延迟设置为
0
,这里没问题。

为了流畅的性能(没有

setTimeout()
),你可以使用
requestAnimationFrame
,它在所有同步JS代码和所有微任务完成后执行,这样浏览器就知道DOM的最终状态,你可以在重新渲染之前改变它页码:

async function show(){
  const snackbar = document.createElement('div');
  snackbar.classList.add("Snackbar-Transition__HiddenState", 'Snackbar');
  snackbar.innerHTML = '&nbsp';
  
  document.querySelector("body").appendChild(snackbar);
  
  requestAnimationFrame(() => {
    console.log('animation frame');
    snackbar.classList.remove("Snackbar-Transition__HiddenState");
    snackbar.classList.add("Snackbar-Transition__DisplayingState");
  });
  
  queueMicrotask(() => console.log('i am a microtask'));
  
}
.Snackbar{
  width: 128px;
  height: 32px;
  background: blue;
  position: absolute;
  left: 50%;
  margin-left: -64px;
  transition: top 500ms;
}
.Snackbar-Transition__HiddenState{
  top: -32px;
}

.Snackbar-Transition__DisplayingState{
  top: 64px;
}
<button onclick="show()">Show</button>

© www.soinside.com 2019 - 2024. All rights reserved.