【问题标题】:Javascript too fast for DOM-manipulation?Javascript 对于 DOM 操作来说太快了?
【发布时间】:2015-05-05 05:04:29
【问题描述】:

在 Javascript 中,我通过 AJAX 从服务器加载一些元素,并为每个数据元素创建一个 <div>,其中包含另一个 div 和一个 <img>。内部 div 包含 2 到 5 行文本。我将其中三个并排排列成一行,然后将下三个放在下一行,依此类推。

但是由于文本的长度不同,我想对每一行中的元素进行一些微调。我希望所有三个图像的顶部边缘都处于相同的高度。为此,我这样做:

  • 将三个<div><div>text</div><img></div>-blocks 插入到它们的容器中。
  • 获取三个<div>text</div>元素的高度,
  • 计算它们的最大值,然后
  • 设置它们的padding-top 属性,使其高度相同。

在 Safari 和 Chrome 中,当我打开控制台并设置断点以查看详细情况时,这可以正常工作。

但是当我在这两个浏览器中关闭断点时,文本差异没有得到正确的填充值。

我很确定,当 javascript 尝试测量文本 div 的高度时,在断点关闭时,浏览器仍在插入三个 dom 元素并渲染图片。因此,它在它们没有最终值的时候测量它们。该脚本读取了错误的值,因此它会将错误的值放入 padding-top-property。

并非所有浏览器都会出现这种情况:

正常运行时(没有控制台和断点),它在以下范围内始终可以正常运行:

  • 火狐
  • 歌剧
  • Internet Explorer(在我的 iMac 上的虚拟机中运行)

但我有这些问题:

  • 野生动物园

我能做些什么来确保在渲染机器完成操作后测量元素高度?


编辑:

我发现了另一个非常重要的细节:

出现问题的原因是图片上方的 text-div 高度。有时文本非常紧密地适合两行。任何一行中多了一个小写字母,这将是三行。

在这种情况下,我的脚本在创建 div 后立即运行,测量高度为 3 行(60 像素),如果此 div 确实包含 3 行文本,那么一切都将是绝对正确的。如果这个 div 真的是 3 行高,我的脚本会以一种完美的方式来操作元素。

但显然,在我的脚本运行几毫秒后,浏览器(Safari 和 Chrome)对字体渲染进行了改进。然后突然文本变成 2 行,这使得 text-div 只有 40 像素高。所以图像向上移动了 20 个像素,这破坏了我刚刚处理的结果(所有图像都在同一个位置)

那么,这是否让您对如何解决问题有任何想法?有没有办法让我的脚本的那部分在所有渲染抛光完成后运行?有onFinishingRenderingImprovementsDone这样的活动吗?

(写于 May 4th 与你同在 = 星球大战日)

【问题讨论】:

  • 当你询问 DOM 一些维度时,它确实在之前计算它们(这也是你应该避免交错修改和查询的原因)。您的问题不是您认为的问题,但如果没有最小的相关可测试示例,我们将无法解决它。
  • 您获得的高度值是正确的,但您是在图像加载之前获得的。加载图像后,将调整高度。您应该在图像上使用load 事件,这样您就可以等待获取高度,直到所有图像都加载完毕。
  • @Guffa:请写一个答案而不是评论,并解释您对图像上的 »load 事件的含义«。
  • @Guffa:不,它与图像无关。如果我将 <img>-element 替换为仅包含文本的 <div>,我会得到完全相同的行为
  • @HubertSchölnast:我不能重复这种行为。我在 Chrome 中试过这个:jsfiddle.net/Guffa/Lunxbr6p

标签: javascript jquery cross-browser dom-manipulation


【解决方案1】:

让你的脚本运行一个短暂的延迟 - setTimeout(function() {[your code here]}, 100)(或者它需要多长时间......) - 看看你是否可以完全避免这个问题?可能不到一秒,对于异步操作,添加很短的等待可能不会引起注意。

【讨论】:

    【解决方案2】:

    可以监控元素的高度,当元素高度发生变化时,可以重新计算内边距。

    例子:

    $.fn.changeHeight = function(callback){
        return this.each(function(i, e){
            var el = $(e), height = el.height();
            window.setInterval(function(){
                var h = el.height();
                if (h != height) {
                    height = h;
                    callback.call(e);
                }
            }, 100);
        });
    };
    
    function rndText() {
        var txt = '';
        for (var i = Math.floor(Math.random() * 20); i >= 0; i--) {
            txt += 'asdf ';
        }
        return txt;
    }
    
    for (var i = 0; i < 10; i++) {
        var d = $('<div>').append(
            $('<div>').prop('contenteditable', true).text(rndText()).changeHeight(resize)
        ).appendTo('body');
    }
    
    resize();
    
    function resize() {
        console.log('resize');
        var height = 0;
        $('body > div').each(function(i, e) {
            var d = $(e);
            var h = d.find('div').height();
            if (h > height) height = h;
        });
        $('body > div').each(function(i, e) {
            var d = $(e);
            d.css('padding-top', height - d.find('div').height());
        });
    }
    

    演示:http://jsfiddle.net/Guffa/Lunxbr6p/2/

    演示中的框是可编辑的,因此您可以更改文本并查看框如何调整大小。

    【讨论】:

      猜你喜欢
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多