为什么IE在渲染一个空的SVG元素时会卡住?

9

我目前在IE 10和11中遇到了一个问题,即 UI Responsiveness 工具中的布局(Layout)导致浏览器标签有时会挂起。我是一个团队中的一员,正在编写一个相当大的 knockout.js web 应用程序,因此找出导致这个问题的确切条件非常困难。据我所知,当页面上的加载指示器HTML被移除并替换为一些div和一个空SVG标记时执行Layout时,浏览器标签会挂起。

我已经确定了空SVG标记是罪魁祸首,但我不知道为什么,而且我不能从页面中删除该标记,因为它是我正在创建的D#数据可视化的重要元素。

这是IE 11提供给我的US Responsiveness报告。我已经放大了有问题的区域,在图片中你可以看到,Layout线程使CPU飙升到100%。

enter image description here

在进入代码示例之前,我的问题是:

为什么将空的SVG元素添加到页面中会导致浏览器标签间歇性地冻结/挂起?

根据我对减少浏览器重绘(reflow)的研究,HTML通过JavaScript以尽可能少的方式附加到DOM中:

var contentHTML = "";
contentHTML += '<div class="axis-title y-axis-title">' + renderString(bindingData.yAxis.title) + "</div>";
contentHTML += '<div class="' + CANVAS_CLASS + '"></div>';
contentHTML += '<svg class="x-axis"></svg>'; // The problematic element

element.innerHTML = contentHTML;

以下是HTML代码(注意:所有的data-bind内容都是为了触发上面的knockout.js绑定处理程序):
<div class="chart" data-bind="
barChart: {
    data: rowData,
    categoryTextKey: 'label',
    valueKey: 'keyOnObject',
    xAxis: {
        title: 'xAxisTitle',
        domain: [-1, 1]
    },
    yAxis: {
        title: 'yAxisTitle'
    },
    onClick: onLabelClick,
    formatValueText: formatPercentage
}
"></div>
    <div class="axis-title y-axis-title">Y Title</div>
    <div class="chart-canvas"></div>
    <svg xmlns="http://www.w3.org/2000/svg" class="x-axis" />
    <div class="axis-title x-axis-title">X Title</div>
</div>

最后,我还使用flexbox CSS规则来布置我的HTML。我不确定这是否会影响此问题,但如果有帮助,以下是CSS代码:
.chart {
    .flexbox();
    .flex-direction(column);
    height: 100%;
    width: 100%;

    .chart-label-click {
        cursor: pointer;
    }

    .chart-header,
    .axis-title,
    .x-axis {
        .flex-grow(0);
        .flex-shrink(0);
    }

    .chart-canvas {
        .flex-grow(1);
        .flex-shrink(1);

        overflow-x: hidden;
        overflow-y: auto;
        width: 100%;
    }

    .chart-canvas svg {
        display: block;
        width: 100%;
    }

    .axis-title {
        font-weight: bold;
    }

    .x-axis {
        .flexbox();
        .flex-grow(0);
        .flex-basis(20px);

        margin-bottom: 5px;
        overflow: visible;
        width: 100%;
    }

    .x-axis line,
    .x-axis path {
        fill: none;
        stroke: #d1d1d1;
        stroke-width: 1px;
        shape-rendering: crispEdges;
    }
}

谢谢您的帮助。我不确定如何解决这个问题,因为它在我们应用程序的一个部分是间歇性的,而且我们的代码库非常庞大,很难确定其他文件中可能会对此问题产生影响的确切代码组合。

应该使用 var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg"); 创建 <svg>,然后使用 svg.setAttributeNS(...)。另一种方法是使用 importNode() - Alvin K.
你尝试过将svg元素嵌入到<iframe><object><embed>中吗?另外,尝试在JSFiddle页面中隔离此问题,这样您可以更好地诊断,其他人也可以轻松帮助测试和调试。 - Oriol
4个回答

4

1
我最终解决了这个问题,方法是在 .chart 元素上删除使用 display:flex,并使用固定高度和 display:block 替代。看起来这最终是IE在混合SVG和flexbox时的一个bug。

1

确保你的代码不会在 JavaScript(或其他语言)中设置一个没有引号的值,例如以下内容...

var a = ;//[var][space][a][space][=][space][;]

那会导致IE11冻结(不确定10是否也会)。

0

经过多日的搜索,我决定解决这个问题:

svg use { pointer-events:none; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接