前端开发者必须要知道网页是如何渲染的
【编者按】其实,有关网页渲染的文章很多,但是相关信息比较分散,且论述并不是很完整。如果要想对这个主题有个大致的了解,我们还得学习很多知识。因此,Web开发者Alexander Skutin 决定写一篇文章。他相信,这篇文章不仅能帮助初学者,也能对那些想要刷新知识结构的高级前端开发者有所裨益。原文地址
译文如下:
网页渲染必须在很早的阶段进行,可以早到页面布局刚刚定型。因为样式和脚本都会对网页渲染产生关键性的影响。所以专业开发者必须了解一些技巧,从而避免在实践的过程中遇到性能问题。
这篇文章不会研究浏览器内部的详细机制,而是提出一些通用的规则。毕竟,不同浏览器引擎的工作机制各不相同,这无疑会让开发者对浏览器特性的研究变得更加复杂。
浏览器是如何完成网页渲染?
首先,我们回顾一下网页渲染时,浏览器的动作:
根据来自服务器端的HTML代码形成文档对象模型(DOM)
加载并解析样式,形成CSS对象模型。
在文档对象模型和CSS对象模型之上,创建一棵由一组待生成渲染的对象组成的渲染树(在Webkit中这些对象被称为渲染器或渲染对象,而在Gecko中称之为“frame”。)渲染树反映了文档对象模型的结构,但是不包含诸如标签或含有display:none属性的不可见元素。在渲染树中,每一段文本字符串都表现为独立的渲染器。每一个渲染对象都包含与之对应的DOM对象,或者文本块,还加上计算过的样式。换言之,渲染树是一个文档对象模型的直观展示。
对渲染树上的每个元素,计算它的坐标,称之为布局。浏览器采用一种流方法,布局一个元素只需通过一次,但是表格元素需要通过多次。
最后,渲染树上的元素最终展示在浏览器里,这一过程称为“painting”。
当用户与网页交互,或者脚本程序改动修改网页时,前文提到的一些操作将会重复执行,因为网页的内在结构已经发生了改变。
重绘
当改变那些不会影响元素在网页中的位置的元素样式时,譬如background-color(背景色), border-color(边框色), visibility(可见性),浏览器只会用新的样式将元素重绘一次(这就是重绘,或者说重新构造样式)。
重排
当改变影响到文本内容或结构,或者元素位置时,重排或者说重新布局就会发生。这些改变通常由以下事件触发:
DOM操作(元素添加,删除,修改,或者元素顺序的改变);
内容变化,包括表单域内的文本改变;
CSS属性的计算或改变;
添加或删除样式表;
更改“类”的属性;
浏览器窗口的操作(缩放,滚动);
伪类激活(:悬停)。
浏览器如何优化渲染?
浏览器尽可能将重绘/重构 限制在被改变元素的区域内。比如,对于位置固定或绝对的元素,其大小改变只影响元素本身及其子元素,然而,静态定位元素的大小改变会触发后续所有元素的重流。
另一种优化技巧是,在运行几段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');
其结果就是,重排发生了两次。因此,你应该把访问元素属性的操作都组织在一起,从而优化网页性能。(你可以在JSBin查到更为详细的例子)
有时,你必须触发一个强制性重排。比如,我们必须将同样的属性(比如左边距)两次赋值给同一个元素。起初,它应该设置为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选择器的性能排名(从最快者开始)
1. 识别器:#id 2. 类:.class 3. 标签:div 4. 相邻兄弟选择器:a + i 5. 父类选择器:ul> li 6. 通用选择器:* 7. 属性选择:input[type="text"] 8. 伪类和伪元素:a:hover
你应该记住,浏览器在处理选择器时依照从右到左的原则,因此最右端的选择器应该是最快的:#id或则.class:div * {...} // bad .list li {...} // bad .list-item {...} // good #list .list-item {...} // good * 1.在你的脚本代码中,尽可能减少DOM操作。缓存所有东西,包括元素属性以及对象(如果它们被重用的话)。当进行复杂的操作时,使用“孤立”元素会更好,之后可以将其加到DOM中(所谓“孤立”元素是与DOM脱离,仅保存在内存中的元素)。
2.如果你使用jQuery来选择元素,请遵从jQuery选择器最佳实践方案。
3.为了改变元素的样式,修改“类”的属性是奏效的方法之一。执行这一改变时,处在DOM渲染树的位置越深越好(这还有助于将逻辑与表象脱离)。
4.尽量只给位置绝对或者固定的元素添加动画效果。
5.在使用滚动时禁用复杂的悬停动效(比如,在中添加一个额外的不悬停类)。读者可以阅读关于这个问题的一篇文章。
想了解更多的细节问题,大家也可以看看这两篇文章:
1,How browsers work?
2,Rendering: repaint, reflow/relayout, restyle

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Aliran pembangunan bahagian hadapan sentiasa berkembang, dan sesetengah aliran kekal popular untuk masa yang lama. Artikel ini meringkaskan beberapa trend pembangunan bahagian hadapan yang akan diserlahkan pada tahun 2023 dan berkongsinya dengan anda~

Dengan perkembangan pesat Internet, teknologi pembangunan bahagian hadapan juga sentiasa bertambah baik dan berulang. PHP dan Angular ialah dua teknologi yang digunakan secara meluas dalam pembangunan bahagian hadapan. PHP ialah bahasa skrip sebelah pelayan yang boleh mengendalikan tugas seperti memproses borang, menjana halaman dinamik dan mengurus kebenaran akses. Angular ialah rangka kerja JavaScript yang boleh digunakan untuk membangunkan aplikasi satu halaman dan membina aplikasi web berkomponen. Artikel ini akan memperkenalkan cara menggunakan PHP dan Angular untuk pembangunan bahagian hadapan, dan cara menggabungkannya

Semalam saya baru sahaja menyiarkan tajuk mikro tentang koleksi lengkap perpustakaan pembangunan desktop Python, dan rakan sekerja saya menemui perpustakaan Flet. Ini adalah perpustakaan yang sangat baru. Versi pertama hanya dikeluarkan pada bulan Jun tahun ini. Walaupun ia sangat baru, ia disokong oleh Flutter gergasi dan membolehkan kami menggunakan Python untuk membangunkan perisian platform penuh semua platform, Mengikut rancangan penulis, apa sahaja yang disokong oleh Flutter, ia akan menyokong pada masa hadapan saya telah mengkajinya secara ringkas semalam dan ia sangat hebat. Kita boleh menggunakannya untuk melakukan beberapa perkara kemudian. Apa itu FletFlet ialah rangka kerja yang membolehkan membina aplikasi web, desktop dan mudah alih berbilang pengguna interaktif dalam bahasa kegemaran anda tanpa perlu mempunyai pengalaman dengan pembangunan bahagian hadapan. tuan rumah

Pembangunan bahagian hadapan dan bahagian belakang adalah dua aspek penting untuk membina aplikasi web yang lengkap Terdapat perbezaan yang jelas antara mereka, tetapi ia berkait rapat. Artikel ini akan menganalisis perbezaan dan perkaitan antara pembangunan front-end dan back-end. Mula-mula, mari kita lihat definisi dan tugas khusus pembangunan bahagian hadapan dan pembangunan bahagian belakang. Pembangunan bahagian hadapan bertanggungjawab terutamanya untuk membina antara muka pengguna dan bahagian interaksi pengguna, iaitu, perkara yang dilihat dan dikendalikan oleh pengguna dalam penyemak imbas. Pembangun bahagian hadapan biasanya menggunakan teknologi seperti HTML, CSS dan JavaScript untuk melaksanakan reka bentuk dan kefungsian halaman web

Untuk menguasai peranan sessionStorage dan meningkatkan kecekapan pembangunan bahagian hadapan, contoh kod khusus diperlukan Dengan perkembangan pesat Internet, bidang pembangunan bahagian hadapan juga berubah setiap hari. Apabila melakukan pembangunan bahagian hadapan, kita selalunya perlu memproses sejumlah besar data dan menyimpannya dalam penyemak imbas untuk kegunaan seterusnya. SessionStorage ialah alat pembangunan bahagian hadapan yang sangat penting yang boleh memberikan kami penyelesaian storan tempatan sementara dan meningkatkan kecekapan pembangunan. Artikel ini akan memperkenalkan peranan sessionStorage,

node.red merujuk kepada Node-RED, alat pengaturcaraan kod rendah berasaskan aliran untuk menyambungkan peranti perkakasan, API dan perkhidmatan dalam talian dengan cara baharu dan menarik ia menyediakan editor berasaskan pelayar yang membolehkan Kita boleh menyambung aliran bersama-sama dengan mudah; pelbagai nod dalam panel edit dan gunakannya ke masa jalannya dengan hanya satu klik.

Ringkasan pengalaman dalam permintaan asynchronous JavaScript dan pemprosesan data dalam pembangunan front-end Dalam pembangunan front-end, JavaScript adalah bahasa yang sangat penting Ia bukan sahaja boleh mencapai kesan interaktif dan dinamik pada halaman, tetapi juga mendapatkan dan memproses data melalui permintaan tak segerak. . Dalam artikel ini, saya akan meringkaskan beberapa pengalaman dan petua apabila berurusan dengan permintaan dan data tak segerak. 1. Gunakan objek XMLHttpRequest untuk membuat permintaan tak segerak Objek XMLHttpRequest digunakan oleh JavaScript untuk menghantar

Trend baharu di bahagian hadapan Golang: Tafsiran prospek aplikasi Golang dalam pembangunan bahagian hadapan Dalam beberapa tahun kebelakangan ini, bidang pembangunan bahagian hadapan telah berkembang pesat, dan pelbagai teknologi baharu telah muncul dalam aliran yang tidak berkesudahan dan bahasa pengaturcaraan yang boleh dipercayai, Golang juga telah mula muncul dalam pembangunan bahagian hadapan. Golang (juga dikenali sebagai Go) ialah bahasa pengaturcaraan yang dibangunkan oleh Google Ia terkenal dengan prestasi yang cekap, sintaks ringkas dan fungsi yang berkuasa, dan secara beransur-ansur digemari oleh pembangun bahagian hadapan. Artikel ini akan meneroka aplikasi Golang dalam pembangunan bahagian hadapan.
