JavaScript创建的内联样式与JavaScript创建的样式表之间的性能差异

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (70)

我想在我的DOM中动态设置给定选择器的所有元素。我或多或少地看到了两种方式。对于下面的例子,我将使用一个p元素,它的text-align属性,但我更喜欢两种可能的做法的优点和缺点,比我在特定的文本对齐段落。

1.内联(每个元素)样式

var nodes = document.getElementsByTagName('p');
Array.prototype.forEach.call (nodes, function (node) {
     node.style.textAlign = "center";
});

2.样式表

var sheet = (function() {
  // Create the <style> tag
  var style = document.createElement("style");

  // WebKit hack :(
  style.appendChild(document.createTextNode(""));

  // Add the <style> element to the page
  document.head.appendChild(style);

  return style.sheet;
})();

sheet.insertRule("p { text-align: center; }");

通常我会选择内联样式的路线,因为它看起来更简单,它确保样式更改将覆盖现有样式表。但是对我来说,对于我来说,有一种情况是:有时候不会覆盖样式表可能更可取,而对于两种:修改一个style元素的性能可能会高于未知数量的p元素。但那只是我的假设。

性能方面,是否会有将内联样式应用于每个单独元素会比创建样式表更好的情况?假设答案可能取决于我设计的元素数量,那么创建样式表的过程会变得更有效率?

编辑:为了澄清为什么我问这个问题,我会解释一下为什么我问:我最近把一些我经常复制粘贴的JS黑客入侵,并在两个项目之间调整为一组可重复使用的CommonJS模块。他们在给定选择器的所有元素设置为高度或宽度与最高或最宽的设置相同的情况下,在最大或最宽的测量值可能会在窗口大小调整或其他触发器上发生变化的情况下。

这是一篇关于它的博客文章:http : //davejtoews.com/blog/post/javascript-layout-hacks

以下是模块的GitHub仓库:

在这一点上,所有这些模块使用内联样式,但我正在考虑将它们切换到样式表。我找不到任何一种方法的优点和缺点,所以我在这里发布了这个问题。

提问于
用户回答回答于

我对你的问题没有很好的一般回答(我不确定是否有),但是我已经使用开发工具时间表在Chrome 57.0.2987.98测试版上发布的示例运行了一些实验。

下面是在单帧中完成的工作细分,它使用内联样式(左)和动态样式表(右)更新10,000个<p>元素

作为比较,下面是100个<p>元素的相同测试的结果:

总之,对于少数元素,差异可以忽略不计。对于大量的元素,当使用内联样式时,浏览器会花费更多的时间脚本(这是可以预料的,因为存在很大的循环)并重新计算样式(我认为这可以通过浏览器解析一种样式来解释规则每个元素而不是一个单一的通用样式规则)。

所有其他步骤大约需要相同的时间。特别是,使用内联样式时,绘制时间不会增加。

作为参考,我使用了以下测试页面。

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <button id="add-stylesheet">Stylesheet</button>
    <button id="add-inline-styles">Inline</button>
    <script type="text/javascript">
        let stylesheet = document.getElementById('add-stylesheet');
        let inline = document.getElementById('add-inline-styles');

        stylesheet.addEventListener('click', addStylesheet);
        inline.addEventListener('click', addInlineStyles);

        function addStylesheet() {
            let style = document.createElement("style");
            style.appendChild(document.createTextNode(""));
            document.head.appendChild(style);
            style.sheet.insertRule('p { text-align: center }', 0);
        }

        function addInlineStyles() {
            let nodes = document.getElementsByTagName('p');
            for (let node of nodes) {
                node.style.textAlign = 'center';
            }
        }

        // initialize <p> elements
        init(10000);
        function init(numElements) {
            for (let i = 0; i < numElements; ++i) {
                let p = document.createElement('p');
                p.innerText = 'testing'
                document.body.appendChild(p);
            }
        }
    </script>
</html>
用户回答回答于

内联样式的优点和缺点

自从React和JSX获得巨大的普及以来,在过去几年中就这个问题引发了很多争论。

我试过一些解决方案,所以我会在这里列出来。首先是一般性讨论..

CSS基本上是唯一倡导使用全局命名空间的语言,这是人们摆脱直接的CSS和繁重的总体框架的首要原因。使用flexbox,响应式布局可以通过多行代码完成,而不是整个网格系统,例如您可以通过引导程序获得。

CSS解决了以可重用的方式为文档提供样式的问题,但随着应用程序变得更加庞大和复杂,并且包含更多包含自己CSS的第三方库,全球名称空间冲突的可能性几乎变得无法避免。以至于创作和倡导一些不同的模式,比如BEM和SMACSS。

随之而来的反应是管理和创建可重用的内联样式相对简单。你可以使用所有的JavaScript,这意味着你可以使用诸如_.extendor之类的东西来覆盖样式Object.assign。这样可以方便地共享包含组件和样式的模块和包,并且不需要任何类型的样式加载器,例如使用时需要的样式webpack。不过,这并不是全部玫瑰。诸如:hover其他伪选择器和媒体查询之类的东西在普通的内联样式中不受支持。

为了解决这些限制,开发人员实现了触发样式更改的事件,例如onmouseover悬停,以及挂钩到窗口调整大小事件以进行媒体查询。此后不久,一个图书馆来标准化这些js事件,并定义了一个类似于API的CSS被创建并获得了普及,称为Radium。在野外,镭还不公平(相信我,我尝试过)。在大型应用程序中,只有下载了所有的JS之后,才能执行任何媒体查询,我不建议这样做!

这导致了一些采用不同方法的新工具的创建。这些新一代工具使用JS中定义的样式,但生成CSS。这为您提供了内联样式的全部功能以及CSS的全部功能。两全其美。哪个库最好可能取决于你的用例,但这些库由Fela.js,Aphrodite和JSS组成。

我最喜欢的解决方案是Fela.js. 在fela.js.org上查看。Fela可能是您将要获得的最佳表现,并且不是特定于任何特定框架。这就是说它适用于React和React Native。它有一些简洁的功能,比如允许你从你的风格中使用道具。你renderer在页面的头部设置了一个。Fela最适合SSR,但也可以根据您的需求纯粹依靠客户端。当与SSR一起使用时,你可以获得快速的页面加载,因为Fela优化了你写入原子css类的样式,并且它们在初始请求时被发送回客户端。

如果您担心尽快获得最快的页面,这些工具非常棒。您可以轻松完成难点模式,如关键路径css优化,其中必要的样式作为初始HTTP请求的一部分返回,而不是链接到还必须下载的外部工作表。

最后,我不得不提到CSS模块。它们会创建一个外部样式表,但允许您为每个模块仍然使用名称空间CSS。这使您可以编写真正的CSS或SASS等,但会带来额外的安装开销。例如,在webpack中,您需要使用假样式加载器和文本提取工具的组合来创建.css文件。

扫码关注云+社区