Javascript 有没有';元素渲染';事件

Javascript 有没有';元素渲染';事件,javascript,dom,Javascript,Dom,我需要准确地测量web应用程序中文本的尺寸,我通过创建一个元素(使用相关的CSS类),设置其innerHTML,然后使用appendChild将其添加到容器中来实现这一点 执行此操作后,在渲染元素之前需要等待一段时间,然后才能读取元素的偏移宽度,以了解文本的宽度 目前,我正在使用setTimeout(processText,100)等待渲染完成 是否有任何回调我可以听,或更可靠的方式告诉我什么时候我创建的元素已经被呈现?目前没有DOM事件表明元素已经被完全呈现(例如,附加的CSS应用和绘制)。这

我需要准确地测量web应用程序中文本的尺寸,我通过创建一个元素(使用相关的CSS类),设置其
innerHTML
,然后使用
appendChild
将其添加到容器中来实现这一点

执行此操作后,在渲染元素之前需要等待一段时间,然后才能读取元素的
偏移宽度
,以了解文本的宽度

目前,我正在使用
setTimeout(processText,100)
等待渲染完成


是否有任何回调我可以听,或更可靠的方式告诉我什么时候我创建的元素已经被呈现?

目前没有DOM事件表明元素已经被完全呈现(例如,附加的CSS应用和绘制)。这会使一些DOM操作代码返回错误或随机结果(例如获取元素的高度)

使用setTimeout为浏览器提供一些渲染开销是最简单的方法。使用

setTimeout(function(){}, 0)
可能是最实际准确的,因为它将您的代码毫不延迟地放在活动浏览器事件队列的末尾-换句话说,您的代码在渲染操作(以及当时发生的所有其他操作)之后立即排队。

Swizec Teller建议使用
requestAnimationFrame
,并检查元素的
大小

function try() {
    if (!$("#element").size()) {
        window.requestAnimationFrame(try);
    } else {
        $("#element").do_some_stuff();
    }
};
实际上,它只重试一次。因为无论发生什么情况,在下一个渲染帧之前,无论是60秒还是一分钟,元素都将被渲染


例如,当你制作

var clonedForm = $('#empty_form_to_clone').clone(true)[0];

var newForm = $(clonedForm).html().replace(/__prefix__/g, next_index_id_form);

// next_index_id_form is just a integer 
我在这里干什么?
我克隆一个已经呈现的元素,并更改要呈现的html

接下来,我将该文本附加到一个容器中

$('#container_id').append(newForm);
当我想将事件处理程序添加到newForm中的按钮时,问题就出现了,WELL,只需使用ready事件即可

$(clonedForm).ready(function(event){
   addEventHandlerToFormButton();
})
我希望这对你有帮助


PS:对不起,我的英语不好。

被接受的答案是2014年的,现在已经过时了。
setTimeout
可以工作,但它不是最干净的,也不一定保证元素已添加到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!
从2018年起,当元素添加到DOM中时,您应该使用a来检测。现在所有现代浏览器(Chrome 26+、Firefox 14+、IE11、Edge、Opera 15+等)都广泛支持MutationObserver

将元素添加到DOM后,您将能够检索其实际维度

下面是一个简单的示例,说明如何使用
MutationObserver
来侦听向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!
为简洁起见,我使用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!
var myElement=$(“你好世界”)[0];
var观察者=新的突变观察者(功能(突变){
if(document.contains(myElement)){
log(“它在DOM中!”);
observer.disconnect();
}
});
observe(文档,{attributes:false,childList:true,characterData:false,subtree:true});
$(“正文”)。附加(myElement);//console.log:它在DOM中!
每当从
文档中添加或删除任何节点时,
观察者
事件处理程序将触发。在处理程序内部,我们然后执行
contains
检查,以确定
myElement
现在是否在
文档中

您不需要迭代存储在
translations
中的每个MutationRecord,因为您可以直接在
myElement
上执行
文档。contains
检查


为了提高性能,将
document
替换为将在DOM中包含
myElement
的特定元素。

MutationObserver可能是最好的方法,但这里有一个简单的替代方法可以工作

我有一些javascript为一个大表构建HTML,并将div的innerHTML设置为生成的HTML。如果在设置innerHTML后立即获取
Date()
,我发现时间戳是在表完全呈现之前的一段时间。我想知道渲染需要多长时间(这意味着在渲染完成后我需要检查
Date()
)。我发现可以通过设置div的innerHTML,然后(在相同的脚本中)调用页面上某个按钮的click方法来实现这一点。单击处理程序将仅在HTML完全呈现之后执行,而不仅仅是在设置了div的innerHTML属性之后。我通过比较click处理程序生成的Date()值与设置div的innerHTML属性的脚本检索到的Date()值来验证这一点


希望有人觉得这个有用

假设您的元素有classname class=“test” 如果发生更改,以下功能将继续测试 如果是,请运行该函数

        function addResizeListener(elem, fun) {
            let id;
            let style = getComputedStyle(elem);
            let wid = style.width;
            let hei = style.height;
            id = requestAnimationFrame(test)
            function test() {
                let newStyle = getComputedStyle(elem);
                if (wid !== newStyle.width ||
                    hei !== newStyle.height) {
                    fun();
                    wid = newStyle.width;
                    hei = newStyle.height;
                }
                id = requestAnimationFrame(test);
            }
        }
        let test = document.querySelector('.test');
        addResizeListener(test,function () {
            console.log("I changed!!")
        });

根据@Elliot B.的回答,我制定了一个适合我的计划

const callback=()=>{
const el=document.querySelector('a');
如果(el){
observer.disconnect();
el.addEventListener('click',()=>{});
}
};
const observer=新的MutationObserver(回调);
observer.observe(document.body,{subtree:true,childList:true});

在我的例子中,像
setTimeout
MutationObserver
这样的解决方案不是完全可行的。 相反,我使用了ResizeObserver。根据:

如果实现遵循规范,则应调用 在绘制之前和布局之后调整事件大小

因此,基本上,观察者总是在布局之后激发,因此我们应该能够得到被观察元素的正确尺寸。 作为奖励,观察者已经返回元素的维度。因此,我们甚至不需要调用类似于
offsetWidth
的东西(即使它也应该可以工作)

constmyelement=document.createElement(“div”);
myElement.textContent=“测试字符串”;
常数