我想在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 hack变成了一组可重用的CommonJS模块。在窗口调整大小或其他触发器上最高或最宽的度量可能会发生变化的情况下,它们会将给定选择器的所有元素设置为与集合中的最高或最宽元素相同的高度或宽度。
这里有一篇关于它的博客文章:http://davejtoews.com/blog/post/javascript-layout-hacks
以下是模块的GitHub代码库:
在这一点上,所有这些模块都使用内联样式,但我正在考虑将它们转换为样式表。关于这两种方法的优缺点,我都找不到一个好的答案,所以我在这里贴出了这个问题。
发布于 2017-03-11 04:10:58
我对你的问题没有一个很好的通用答案(我也不确定有没有),但我已经用你在Chrome57.0.2987.98测试版上发布的例子,使用开发工具时间线运行了一些实验。
以下是在单个框架中完成的工作的细目,该框架使用内联样式(左)和动态样式表(右)更新10,000 <p>
elements:
为了进行比较,以下是使用100 <p>
elements进行相同测试的结果
总而言之,对于少数元素,差异可以忽略不计。对于大量的元素,当使用内联样式时,浏览器花费更多的时间来编写脚本(这是意料之中的,因为有一个繁重的循环)和重新计算样式(我认为这可以解释为浏览器必须为每个元素解析一个样式规则,而不是一个通用的样式规则)。
所有其他步骤都需要大致相同的时间。特别是,使用内联样式时,绘制时间不会增加。
作为参考,我使用了以下测试页面。
<!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>
发布于 2017-03-01 07:53:05
内联样式的优缺点
自从React和JSX获得了巨大的人气以来,在过去的几年里,关于这个主题已经有了很多争论。
我已经尝试了一些解决方案,所以我将在这里列出它们。首先是一般性的讨论..
CSS基本上是唯一一种提倡使用全局名称空间的语言,这也是人们远离简单的CSS和沉重的拱形框架的首要原因。使用flexbox,响应式布局可以在几行代码中完成,而不是像bootstrap这样的整个网格系统。
CSS解决了以可重用的方式向文档提供样式的问题,但随着应用程序变得越来越庞大和复杂,以及包含更多具有自己的CSS的第三方库,全局命名空间冲突的机会几乎是不可避免的。以至于一些不同的模式被创作和提倡,比如BEM和SMACSS。
react的出现使得管理和创建可重用的内联样式变得相对简单。你可以使用所有的javascript,这意味着你可以使用像_.extend
或Object.assign
这样的东西覆盖样式。这使得很容易共享包含组件及其样式的模块和包,并且不需要任何类型的样式加载器,例如使用webpack
时所需的样式加载器。然而,并不是所有的事情都是美好的。在纯内联样式中不支持:hover
、其他伪选择器和媒体查询。
为了绕过这些限制,开发人员实现了一些事件来触发样式更改,比如用于悬停的onmouseover
,以及用于媒体查询的窗口调整事件。不久之后,创建了一个名为Radium
的库,用于标准化这些js事件,并定义一个类似CSS的API。在野外,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文件。
发布于 2017-03-02 02:53:56
这完全取决于你想要实现的目标的上下文。在我目前的雇主,我最终创建了一个名为stylo的小型库,它负责更新动态样式表。
当您尝试更新的项目数量达到数千个时,通过内联样式进行更新将是非常昂贵的。上面链接中的demo在不到一秒的时间内更新了6,400个项目。
但是,如果只更新少数几个项,更新样式表可能会触发整个页面重新呈现,如果更新了内联样式,则不会发生这种情况。
https://stackoverflow.com/questions/42428311
复制相似问题