资讯专栏INFORMATION COLUMN

每个前端开发人员应该知道的网页呈现

hikui / 497人阅读

摘要:每个文本字符串在渲染树中作为多带带的渲染器表示。对于每个渲染树元素,计算其坐标,称为布局。最后,这实际上显示在浏览器窗口中,一个称为绘画的过程。尝试简化和优化选择器这种优化几乎被大多数使用预处理器的开发人员普遍忽略。

2014年5月26日, 由Alexander Skutin撰写; 由Max Shirshin于2014年6月30日翻译

今天我想关注网页呈现的主题,以及为什么它在网页开发中很重要。有很多文章可用于涵盖这个主题,但是信息是分散的,以某种方式分散。例如,为了包围我的头脑,我不得不学习很多来源。这就是为什么我决定写这篇文章。我相信这篇文章对于初学者以及想要刷新和构建他们已经知道的更多高级开发人员将是有用的。

当页面布局被定义时,渲染必须从一开始就进行优化,因为样式和脚本在页面呈现中起关键作用。专业人士必须了解某些技巧以避免性能问题。

本文不详细研究内部浏览器的机制,而是提供一些常见的原则。不同的浏览器引擎的工作方式不同,这将使浏览器特定的研究变得更加复杂。

浏览器如何呈现网页
我们从绘制页面时浏览浏览器操作的概述开始:

1.DOM(文档对象模型)由从服务器接收的HTML形成。
2.样式被加载和解析,形成了CSSOM(CSS对象模型)。
3.在DOM和CSSOM之上,创建一个渲染树,它是一组要渲染的对象(Webkit调用那些“渲染器”或“渲染对象”,而在Gecko中它是一个“框架”)。渲染树反映除了不可见元素之外的DOM结构(如标签或已display:none;设置的元素)。每个文本字符串在渲染树中作为多带带的渲染器表示。每个渲染对象都包含其对应的DOM对象(或文本块)加上计算的样式。换句话说,渲染树描述了DOM的视觉表示。
对于每个渲染树元素,计算其坐标,称为“布局”。浏览器使用一个流程方法,只需要一次传递来布局所有元素(表需要多个遍)。
最后,这实际上显示在浏览器窗口中,一个称为“绘画”的过程。
当用户与页面进行交互或脚本进行修改时,必须重复上述某些操作,因为底层页面结构发生变化。

重印
当改变不影响页面上的元素的位置元素的样式(例如background-color,border-color,visibility),浏览器只是应用了新样式再次重绘元素(即意味着“重画”或“restyle”正在发生的事情)。

回流
当更改影响文档内容或结构或元素位置时,会发生回流(或重新传输)。这些更改通常是由以下机制触发的:

DOM操作(元素添加,删除,更改或更改元素顺序);
内容更改,包括表单字段中的文本更改;
1计算或改变CSS属性;
2添加或删除样式表;
3改变“类”属性;
4浏览器窗口操纵(调整大小,滚动);
5伪类激活(:hover)。
浏览器如何优化渲染
浏览器正在尽最大努力将重绘/回流限制到仅覆盖已更改元素的区域。例如,绝对/固定定位元素中的大小变化仅影响元素本身及其后代,而静态定位元素中的相似变化会触发所有后续元素的回流。

另一种优化技术是在运行JavaScript代码时,浏览器会缓存这些更改,并在代码运行后将其应用于单次传递。例如,这段代码只会触发一个回流和重绘:

var $body = $("body");
$body.css("padding", "1px"); // reflow, repaint
$body.css("color", "red"); // repaint
$body.css("margin", "2px"); // reflow, repaint
// only 1 reflow and repaint will actually happen
但是,如上所述,访问元素属性会触发强制回流。如果我们添加一个额外的行,将元素属性读入上一个块,则会发生这种情况:

var $body = $("body");
$body.css("padding", "1px");
$body.css("padding"); // reading a property, a forced reflow
$body.css("color", "red");
$body.css("margin", "2px");

因此,我们得到2个回流而不是一个回流。因此,您应该将读取元素属性组合在一起以优化性能(请参阅 JSBin上的更详细示例)。

有时您必须触发强制回流。示例:我们必须将相同的属性(例如“margin-left”)应用于同一个元素两次。最初,它应该被设置为100px没有动画,然后它必须是动画与transition一个值50px。您现在可以在JSBin上学习这个例子,但是我将在这里进行更详细的描述。

我们首先创建一个具有转换的CSS类:

.has-transition {
-webkit-transition: margin-left 1s ease-out;

  -moz-transition: margin-left 1s ease-out;
    -o-transition: margin-left 1s ease-out;
       transition: margin-left 1s ease-out;

}
然后继续执行:

// our element that has a "has-transition" class by default
var $targetElem = $("#targetElemId");

// remove the transition class
$targetElem.removeClass("has-transition");

// change the property expecting the transition to be off, as the class is not there
// anymore
$targetElem.css("margin-left", 100);

// put the transition class back
$targetElem.addClass("has-transition");

// change the property
$targetElem.css("margin-left", 50);
然而,这种实现不能像预期的那样工作。这些更改被缓存并应用于代码块的末尾。我们需要的是强制回流,我们可以通过进行以下更改来实现:

// remove the transition class
$(this).removeClass("has-transition");

// change the property
$(this).css("margin-left", 100);

// trigger a forced reflow, so that changes in a class/property get applied immediately
$(this)[0].offsetHeight; // an example, other properties would work, too

// put the transition class back
$(this).addClass("has-transition");

// change the property
$(this).css("margin-left", 50);
现在这样按预期工作。

优化实用建议
总结可用信息,我可以推荐以下内容:

创建有效的HTML和CSS,不要忘记指定文档编码。样式应包含在中,附加到标签末尾的脚本。
尝试简化和优化CSS选择器(这种优化几乎被大多数使用CSS预处理器的开发人员普遍忽略)。保持嵌套水平至少。这是CSS选择器根据其性能(从最快的)开始排名的方式:
识别者: #id
类: .class
标签: div
相邻的兄弟选择器: a + i
家长选择器 ul > li
通用选择器 *
属性选择器 input[type="text"]
伪类和pseudoelements:a:hover 你应该记住,浏览器从右到左的处理选择,这就是为什么最右边的选择应该是最快的国家之一-要么#id或.class:
div * {...} // bad
.list li {...} // bad
.list-item {...} // good

list .list-item {...} // good

在脚本中,尽量减少DOM操作。缓存所有内容,包括属性和对象(如果要重复使用)。执行复杂操作时,最好使用“离线”元素(“离线”元素是从DOM断开并仅存储在内存中),然后将其附加到DOM。
如果您使用jQuery选择元素,请遵循jQuery选择器最佳做法。
要更改元素的样式,修改“类”属性是最有效的方式之一。您执行此更改的DOM树越深,越好(也是因为这有助于将逻辑与演示分离)。
动画只有绝对/固定的元素,如果可以的话。
在:hover滚动时禁用复杂动画是一个好主意(例如,通过向添加一个额外的“no-hover”类)。阅读有关此主题的文章。
有关更详细的概述,请查看这些文章:

浏览器的工作原理
渲染:重绘,回流/重新传输,修复
我希望你能发现这篇文章有用!

2014年6月30日
[RU] РендерингWEB-страницы:чтообэтомдолжензнать前端разработчик
亚历山大Skutin
现场: http://skutin.ru/
Max Shirshin
GitHub: ingdir
推特: @ingdir
Facebook 推特 Google+
如果您发现有错误,请随时在GitHub上进行 编辑。
评论由Disqus提供支持

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/56223.html

相关文章

  • web前端和后端区别在哪?

    摘要:前端和后端是计算机行业最常用的两个术语在某种程度上,它们成了流行语。前端开发人员也称为前端设计师,他们可以创建一个没有任何后端开发的站点。 前端和后端是计算机行业最常用的两个术语;在某种程度上,它们成了流行语。它们决定了你作为软件开发人员的工作类型、你使用的技术以及你得到的报酬。那么,让我们来谈谈这两个术语之间的区别,它们...

    xuxueli 评论0 收藏0
  • web前端学习第一步应该干什么?

    摘要:应用程序是在浏览器上呈现并由用户通过浏览器访问的应用程序。要成为一名开发人员,你可能需要学习其中一种通常不止一种工具。因此,结论是你必须学习基本工具,并将其用作其他较新工具的起点。 Web开发是编写可通过Web浏览器运行和访问的应用程序的领域,web开发领域已经(并且每天都在)经历了巨大的变化。从互联网诞生到现在,web技...

    不知名网友 评论0 收藏0
  • IMWeb前端提升营七天学习总结

    摘要:写在前面月到这天,前端提升营,腾讯大佬们分享个人经验,使出各种前端方面的大招。并且减轻服务器的负担,的原则是按需取数据,可以最大程度的减少冗余请求和响应对服务器造成的负担。控制表单控件的禁用状态。 写在前面 5月24到30这7天,IMWeb前端提升营,腾讯大佬们分享个人经验,使出各种前端方面的大招。从中学习了很多前端方面的知识,也get到了前端学习的方法论,还有一些算法知识等等。 现将...

    mating 评论0 收藏0
  • IMWeb前端提升营七天学习总结

    摘要:写在前面月到这天,前端提升营,腾讯大佬们分享个人经验,使出各种前端方面的大招。并且减轻服务器的负担,的原则是按需取数据,可以最大程度的减少冗余请求和响应对服务器造成的负担。控制表单控件的禁用状态。 写在前面 5月24到30这7天,IMWeb前端提升营,腾讯大佬们分享个人经验,使出各种前端方面的大招。从中学习了很多前端方面的知识,也get到了前端学习的方法论,还有一些算法知识等等。 现将...

    luxixing 评论0 收藏0
  • Nicholas C. Zakas:我热爱互联网技术种种异端

    摘要:图灵社区看来,移动互联网开发会成为下一行业焦点,你觉得呢移动互联网开发已经是焦点了。图灵社区现在有很多基于改进的语言,比如,等等。热爱跨浏览器开发带来的挑战热爱互联网技术的种种异端,热爱业内的同行,热爱你的工具。 非商业转载请注明作译者、出处,并保留本文的原始链接:http://www.ituring.com.cn/article/1791 尼古拉斯·泽卡斯(Nicholas...

    PascalXie 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<