我需要准确测量我的Web应用程序中文本的维度,我通过创建一个元素(具有相关的CSS类)来实现,innerHTML
然后设置它然后使用它将其添加到容器中appendChild
.
执行此操作后,在元素呈现之前有一个等待,offsetWidth
可以读取它以找出文本的宽度.
目前,我正在setTimeout(processText, 100)
等待渲染完成.
是否有我可以收听的回调,或者更可靠的方式告诉我创建的元素何时被渲染?
mys*_*dat 39
目前没有DOM事件表明元素已经完全呈现(例如,附加的CSS应用和绘制).这可能会使一些DOM操作代码返回错误或随机结果(如获取元素的高度).
使用setTimeout为浏览器提供一些渲染开销是最简单的方法.运用
setTimeout(function(){}, 0)
Run Code Online (Sandbox Code Playgroud)
可能是最实际的准确,因为它将您的代码放在活动浏览器事件队列的末尾而没有任何延迟 - 换句话说,您的代码在渲染操作之后排队(以及当时发生的所有其他操作).
Ell*_* B. 27
接受的答案是从2014年开始,现在已经过时了.A setTimeout
可能有效,但它不是最干净的,并不一定能保证元素已添加到DOM中.
今天,您应该使用MutationObserver来检测何时将元素添加到DOM.现在,MutationObservers在所有现代浏览器(Chrome 26 +,Firefox 14 +,IE11,Edge,Opera 15+等)中得到广泛支持.
将元素添加到DOM后,您将能够检索其实际尺寸.
这是一个简单的示例,说明如何MutationObserver
在将元素添加到DOM时使用a 来监听.
为简洁起见,我使用jQuery语法构建节点并将其插入DOM.
var myElement = $("<div>hello world</div>")[0];
var observer = new MutationObserver(function(mutations) {
if (document.contains(myElement)) {
console.log("It's in the DOM!");
observer.disconnect();
}
});
observer.observe(document, {attributes: false, childList: true, characterData: false, subtree:true});
$("body").append(myElement); // console.log: It's in the DOM!
Run Code Online (Sandbox Code Playgroud)
observer
每当添加或删除任何节点时,事件处理程序都将触发document
.在处理程序内部,我们然后执行contains
检查以确定myElement
现在是否在document
.
您不需要遍历存储的每个MutationRecord,mutations
因为您可以document.contains
直接执行检查myElement
.
要提高性能,请document
使用myElement
DOM中包含的特定元素替换.
Rob*_*ene 17
就我而言,解决方案如setTimeout
或MutationObserver
并不完全可靠。相反,我使用了ResizeObserver。根据MDN:
如果遵循规范,实现应该在绘制之前和布局之后调用调整大小事件。
所以基本上观察者总是在布局后触发,因此我们应该能够获得观察到的元素的正确尺寸。作为奖励,观察者已经返回了元素的尺寸。因此我们甚至不需要调用类似的东西offsetWidth
(尽管它也应该有效)
const myElement = document.createElement("div");
myElement.textContent = "test string";
const resizeObserver = new ResizeObserver(entries => {
const lastEntry = entries.pop();
// alternatively use contentBoxSize here
// Note: older versions of Firefox (<= 91) provided a single size object instead of an array of sizes
// https://bugzilla.mozilla.org/show_bug.cgi?id=1689645
const width = lastEntry.borderBoxSize?.inlineSize ?? lastEntry.borderBoxSize[0].inlineSize;
const height = lastEntry.borderBoxSize?.blockSize ?? lastEntry.borderBoxSize[0].blockSize;
resizeObserver.disconnect();
console.log("width:", width, "height:", height);
});
resizeObserver.observe(myElement);
document.body.append(myElement);
Run Code Online (Sandbox Code Playgroud)
我们也可以将其包装在一个方便的异步函数中,如下所示:
function appendAwaitLayout(parent, element) {
return new Promise((resolve, reject) => {
const resizeObserver = new ResizeObserver((entries) => {
resizeObserver.disconnect();
resolve(entries);
});
resizeObserver.observe(element);
parent.append(element);
});
}
// call it like this
appendAwaitLayout(document.body, document.createElement("div")).then((entries) => {
console.log(entries)
// do stuff here ...
});
Run Code Online (Sandbox Code Playgroud)
Yuv*_* A. 13
这篇博文由Swizec Teller撰写,建议使用requestAnimationFrame
并检查size
元素.
function try() {
if (!$("#element").size()) {
window.requestAnimationFrame(try);
} else {
$("#element").do_some_stuff();
}
};
Run Code Online (Sandbox Code Playgroud)
在实践中它只会重试一次.因为无论如何,在下一个渲染帧中,无论是60秒还是一分钟,元素都将被渲染.
小智 5
MutationObserver可能是最好的方法,但这是一个可行的简单选择
我有一些JavaScript,可为大型表格构建HTML,并将div的innerHTML设置为生成的HTML。如果Date()
在设置innerHTML之后立即获取,则发现时间戳是在表格完全呈现之前的一段时间。我想知道渲染花费了多长时间(这意味着Date()
渲染完成后需要检查)。我发现可以通过设置div的innerHTML,然后(在同一脚本中)调用页面上某些按钮的click方法来做到这一点。仅在完全渲染HTML之后,而不是在div的innerHTML属性设置之后,单击处理程序才会执行。我通过将单击处理程序生成的Date()值与设置div的innerHTML属性的脚本检索的Date()值进行比较来验证这一点。
希望有人觉得这有用
归档时间: |
|
查看次数: |
31097 次 |
最近记录: |