摘要:由一道面試題引發(fā)的思考從用戶輸入瀏覽器輸入到頁面最后呈現(xiàn)有哪些過程一道很常規(guī)的題目,考的是基本網(wǎng)絡(luò)原理,和瀏覽器加載,過程。所以抽出時(shí)間研究下瀏覽器渲染頁面的過程。
由一道面試題引發(fā)的思考:
從用戶輸入瀏覽器輸入url到頁面最后呈現(xiàn) 有哪些過程?
一道很常規(guī)的題目,考的是基本網(wǎng)絡(luò)原理,和瀏覽器加載css,js過程。
答案大致如下:
用戶輸入U(xiǎn)RL地址
瀏覽器解析URL解析出主機(jī)名
瀏覽器將主機(jī)名轉(zhuǎn)換成服務(wù)器ip地址(瀏覽器先查找本地DNS緩存列表 沒有的話 再向?yàn)g覽器默認(rèn)的DNS服務(wù)器發(fā)送查詢請求 同時(shí)緩存)
瀏覽器將端口號從URL中解析出來
瀏覽器建立一條與目標(biāo)Web服務(wù)器的TCP連接(三次握手)
瀏覽器向服務(wù)器發(fā)送一條HTTP請求報(bào)文
服務(wù)器向?yàn)g覽器返回一條HTTP響應(yīng)報(bào)文
關(guān)閉連接 瀏覽器解析文檔
如果文檔中有資源 重復(fù)6 7 8 動作 直至資源全部加載完畢
以上答案基本簡述了一個(gè)網(wǎng)頁基本的響應(yīng)過程背后的原理。
但這也只是一部分,瀏覽器獲取數(shù)據(jù)的部分,至于瀏覽器拿到數(shù)據(jù)之后,怎么渲染頁面的,一直沒太關(guān)注。
所以抽出時(shí)間研究下瀏覽器渲染頁面的過程。
通過研究,了解一些基本常識的原理:
為什么要將js放到頁腳部分
引入樣式的幾種方式的權(quán)重
css屬性書寫順序建議
何種類型的DOM操作是耗費(fèi)性能的
瀏覽器渲染主要流程不同的瀏覽器內(nèi)核不同,所以渲染過程不太一樣。
WebKit 主流程
Mozilla 的 Gecko 呈現(xiàn)引擎主流程
由上面兩張圖可以看出,雖然主流瀏覽器渲染過程叫法有區(qū)別,但是主要流程還是相同的。
Gecko 將視覺格式化元素組成的樹稱為“框架樹”。每個(gè)元素都是一個(gè)框架。WebKit 使用的術(shù)語是“呈現(xiàn)樹”,它由“呈現(xiàn)對象”組成。對于元素的放置,WebKit 使用的術(shù)語是“布局”,而 Gecko 稱之為“重排”。對于連接 DOM 節(jié)點(diǎn)和可視化信息從而創(chuàng)建呈現(xiàn)樹的過程,WebKit 使用的術(shù)語是“附加”。
所以可以分析出基本過程:
HTML解析出DOM Tree
CSS解析出Style Rules
將二者關(guān)聯(lián)生成Render Tree
Layout 根據(jù)Render Tree計(jì)算每個(gè)節(jié)點(diǎn)的信息
Painting 根據(jù)計(jì)算好的信息繪制整個(gè)頁面
HTML解析HTML Parser的任務(wù)是將HTML標(biāo)記解析成DOM Tree
這個(gè)解析可以參考React解析DOM的過程,
但是這里面有很多別的規(guī)則和操作,比如容錯(cuò)機(jī)制,識別和
等等。
感興趣的可以參考 《How Browser Work》,中文翻譯
舉個(gè)例子:一段HTML
Web page parsing Web page parsing
This is an example Web page.
經(jīng)過解析之后的DOM Tree差不多就是
將文本的HTML文檔,提煉出關(guān)鍵信息,嵌套層級的樹形結(jié)構(gòu),便于計(jì)算拓展。這就是HTML Parser的作用。
CSS解析CSS Parser將CSS解析成Style Rules,Style Rules也叫CSSOM(CSS Object Model)。
StyleRules也是一個(gè)樹形結(jié)構(gòu),根據(jù)CSS文件整理出來的類似DOM Tree的樹形結(jié)構(gòu):
于HTML Parser相似,CSS Parser作用就是將很多個(gè)CSS文件中的樣式合并解析出具有樹形結(jié)構(gòu)Style Rules。
腳本處理瀏覽器解析文檔,當(dāng)遇到標(biāo)簽的時(shí)候,會立即解析腳本,停止解析文檔(因?yàn)镴S可能會改動DOM和CSS,所以繼續(xù)解析會造成浪費(fèi))。
如果腳本是外部的,會等待腳本下載完畢,再繼續(xù)解析文檔。現(xiàn)在可以在script標(biāo)簽上增加屬性 defer或者async。
腳本解析會將腳本中改變DOM和CSS的地方分別解析出來,追加到DOM Tree和Style Rules上。
Render Tree的構(gòu)建其實(shí)就是DOM Tree和CSSOM Attach的過程。
呈現(xiàn)器是和 DOM 元素相對應(yīng)的,但并非一一對應(yīng)。Render Tree實(shí)際上就是一個(gè)計(jì)算好樣式,與HTML對應(yīng)的(包括哪些顯示,那些不顯示)的Tree。
樣式計(jì)算在 WebKit 中,解析樣式和創(chuàng)建呈現(xiàn)器的過程稱為“附加”。每個(gè) DOM 節(jié)點(diǎn)都有一個(gè)“attach”方法。附加是同步進(jìn)行的,將節(jié)點(diǎn)插入 DOM 樹需要調(diào)用新的節(jié)點(diǎn)“attach”方法。
樣式計(jì)算是個(gè)很復(fù)雜的問題。DOM中的一個(gè)元素可以對應(yīng)樣式表中的多個(gè)元素。樣式表包括了所有樣式:瀏覽器默認(rèn)樣式表,自定義樣式表,inline樣式元素,HTML可視化屬性如:width=100。后者將轉(zhuǎn)化以匹配CSS樣式。
WebKit 節(jié)點(diǎn)會引用樣式對象 (RenderStyle)。這些對象在某些情況下可以由不同節(jié)點(diǎn)共享。這些節(jié)點(diǎn)是同級關(guān)系,并且:
這些元素必須處于相同的鼠標(biāo)狀態(tài)(例如,不允許其中一個(gè)是“:hover”狀態(tài),而另一個(gè)不是)
任何元素都沒有 ID
標(biāo)記名稱應(yīng)匹配
類屬性應(yīng)匹配
映射屬性的集合必須是完全相同的
鏈接狀態(tài)必須匹配
焦點(diǎn)狀態(tài)必須匹配
任何元素都不應(yīng)受屬性選擇器的影響,這里所說的“影響”是指在選擇器中的任何位置有任何使用了屬性選擇器的選擇器匹配
元素中不能有任何 inline 樣式屬性
不能使用任何同級選擇器。WebCore 在遇到任何同級選擇器時(shí),只會引發(fā)一個(gè)全局開關(guān),并停用整個(gè)文檔的樣式共享(如果存在)。這包括 + 選擇器以及 :first-child 和 :last-child 等選擇器。
為了簡化樣式計(jì)算,F(xiàn)irefox 還采用了另外兩種樹:規(guī)則樹和樣式上下文樹。WebKit 也有樣式對象,但它們不是保存在類似樣式上下文樹這樣的樹結(jié)構(gòu)中,只是由 DOM 節(jié)點(diǎn)指向此類對象的相關(guān)樣式。
樣式上下文包含端值。要計(jì)算出這些值,應(yīng)按照正確順序應(yīng)用所有的匹配規(guī)則,并將其從邏輯值轉(zhuǎn)化為具體的值。
例如,如果邏輯值是屏幕大小的百分比,則需要換算成絕對的單位。規(guī)則樹的點(diǎn)子真的很巧妙,它使得節(jié)點(diǎn)之間可以共享這些值,以避免重復(fù)計(jì)算,還可以節(jié)約空間。
所有匹配的規(guī)則都存儲在樹中。路徑中的底層節(jié)點(diǎn)擁有較高的優(yōu)先級。規(guī)則樹包含了所有已知規(guī)則匹配的路徑。規(guī)則的存儲是延遲進(jìn)行的。規(guī)則樹不會在開始的時(shí)候就為所有的節(jié)點(diǎn)進(jìn)行計(jì)算,而是只有當(dāng)某個(gè)節(jié)點(diǎn)樣式需要進(jìn)行計(jì)算時(shí),才會向規(guī)則樹添加計(jì)算的路徑。
舉個(gè)例子 我們有段HTML代碼:
this is a big error this is also a very big error error
another error
對應(yīng)CSS規(guī)則如下:
1. .div {margin:5px;color:black} 2. .err {color:red} 3. .big {margin-top:3px} 4. div span {margin-bottom:4px} 5. #div1 {color:blue} 6. #div2 {color:green}
則CSS形成的規(guī)則樹如下圖所示(節(jié)點(diǎn)的標(biāo)記方式為“節(jié)點(diǎn)名 : 指向的規(guī)則序號”)
假設(shè)我們解析 HTML 時(shí)遇到了第二個(gè)
現(xiàn)在我們需要填充樣式結(jié)構(gòu)。首先要填充的是 margin 結(jié)構(gòu)。由于最后的規(guī)則節(jié)點(diǎn) (F) 并沒有添加到 margin 結(jié)構(gòu),我們需要上溯規(guī)則樹,直至找到在先前節(jié)點(diǎn)插入中計(jì)算過的緩存結(jié)構(gòu),然后使用該結(jié)構(gòu)。我們會在指定 margin 規(guī)則的最上層節(jié)點(diǎn)(即 B 節(jié)點(diǎn))上找到該結(jié)構(gòu)。
我們已經(jīng)有了 color 結(jié)構(gòu)的定義,因此不能使用緩存的結(jié)構(gòu)。由于 color 有一個(gè)屬性,我們無需上溯規(guī)則樹以填充其他屬性。我們將計(jì)算端值(將字符串轉(zhuǎn)化為 RGB 等)并在此節(jié)點(diǎn)上緩存經(jīng)過計(jì)算的結(jié)構(gòu)。
第二個(gè) 元素處理起來更加簡單。我們將匹配規(guī)則,最終發(fā)現(xiàn)它和之前的 span 一樣指向規(guī)則 G。由于我們找到了指向同一節(jié)點(diǎn)的同級,就可以共享整個(gè)樣式上下文了,只需指向之前 span 的上下文即可。
對于包含了繼承自父代的規(guī)則的結(jié)構(gòu),緩存是在上下文樹中進(jìn)行的(事實(shí)上 color 屬性是繼承的,但是 Firefox 將其視為 reset 屬性,并緩存到規(guī)則樹上)
所以生成的上下文樹如下:
樣式對象具有與每個(gè)可視化屬性一一對應(yīng)的屬性(均為 CSS 屬性但更為通用)。如果某個(gè)屬性未由任何匹配規(guī)則所定義,那么部分屬性就可由父代元素樣式對象繼承。其他屬性具有默認(rèn)值。
如果定義不止一個(gè),就會出現(xiàn)問題,需要通過層疊順序來解決。
一些例子:
* {} /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */ li {} /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */ li:first-line {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul li {} /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */ ul ol+li {} /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */ h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */ ul ol li.red {} /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */ li.red.level {} /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */ #x34y {} /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */ style="" /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */
利用上面的方法,基本可以快速確定不同選擇器的優(yōu)先級。
布局Layout創(chuàng)建渲染樹后,下一步就是布局(Layout),或者叫回流(reflow,relayout),這個(gè)過程就是通過渲染樹中渲染對象的信息,計(jì)算出每一個(gè)渲染對象的位置和尺寸,將其安置在瀏覽器窗口的正確位置,而有些時(shí)候我們會在文檔布局完成后對DOM進(jìn)行修改,這時(shí)候可能需要重新進(jìn)行布局,也可稱其為回流,本質(zhì)上還是一個(gè)布局的過程,每一個(gè)渲染對象都有一個(gè)布局或者回流方法,實(shí)現(xiàn)其布局或回流。
對渲染樹的布局可以分為全局和局部的,全局即對整個(gè)渲染樹進(jìn)行重新布局,如當(dāng)我們改變了窗口尺寸或方向或者是修改了根元素的尺寸或者字體大小等;而局部布局可以是對渲染樹的某部分或某一個(gè)渲染對象進(jìn)行重新布局。
大多數(shù)web應(yīng)用對DOM的操作都是比較頻繁,這意味著經(jīng)常需要對DOM進(jìn)行布局和回流,而如果僅僅是一些小改變,就觸發(fā)整個(gè)渲染樹的回流,這顯然是不好的,為了避免這種情況,瀏覽器使用了臟位系統(tǒng),只有一個(gè)渲染對象改變了或者某渲染對象及其子渲染對象臟位值為”dirty”時(shí),說明需要回流。
表示需要布局的臟位值有兩種:
“dirty”–自身改變,需要回流
“children are dirty”–子節(jié)點(diǎn)改變,需要回流
布局是一個(gè)從上到下,從外到內(nèi)進(jìn)行的遞歸過程,從根渲染對象,即對應(yīng)著HTML文檔根元素,然后下一級渲染對象,如對應(yīng)著元素,如此層層遞歸,依次計(jì)算每一個(gè)渲染對象的幾何信息(位置和尺寸)。
每一個(gè)渲染對象的布局流程基本如:
1.計(jì)算此渲染對象的寬度(width);
2.遍歷此渲染對象的所有子級,依次:
2.1設(shè)置子級渲染對象的坐標(biāo)
2.2判斷是否需要觸發(fā)子渲染對象的布局或回流方法,計(jì)算子渲染對象的高度(height)
3.設(shè)置此渲染對象的高度:根據(jù)子渲染對象的累積高,margin和padding的高度設(shè)置其高度;
4.設(shè)置此渲染對象臟位值為false。
繪制(Painting)在繪制階段,系統(tǒng)會遍歷呈現(xiàn)樹,并調(diào)用呈現(xiàn)器的“paint”方法,將呈現(xiàn)器的內(nèi)容顯示在屏幕上。繪制工作是使用用戶界面基礎(chǔ)組件完成的。
CSS2 規(guī)范定義了繪制流程的順序。繪制的順序其實(shí)就是元素進(jìn)入堆棧樣式上下文的順序。這些堆棧會從后往前繪制,因此這樣的順序會影響繪制。塊呈現(xiàn)器的堆棧順序如下:
背景顏色
背景圖片
邊框
子代
輪廓
這里還要說兩個(gè)概念,一個(gè)是Reflow,另一個(gè)是Repaint。這兩個(gè)不是一回事。
Repaint ——屏幕的一部分要重畫,比如某個(gè)CSS的背景色變了。但是元素的幾何尺寸沒有變。
Reflow 元件的幾何尺寸變了,我們需要重新驗(yàn)證并計(jì)算Render Tree。是Render Tree的一部分或全部發(fā)生了變化。這就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式布局,所以,如果某元件的幾何尺寸發(fā)生了變化,需要重新布局,也就叫reflow)reflow 會從這個(gè)root frame開始遞歸往下,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置,在reflow過程中,可能會增加一些frame,比如一個(gè)文本字符串必需被包裝起來。
Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每個(gè)結(jié)點(diǎn)都會有reflow方法,一個(gè)結(jié)點(diǎn)的reflow很有可能導(dǎo)致子結(jié)點(diǎn),甚至父點(diǎn)以及同級結(jié)點(diǎn)的reflow。在一些高性能的電腦上也許還沒什么,但是如果reflow發(fā)生在手機(jī)上,那么這個(gè)過程是非常痛苦和耗電的。 所以,下面這些動作有很大可能會是成本比較高的。
當(dāng)你增加、刪除、修改DOM結(jié)點(diǎn)時(shí),會導(dǎo)致Reflow或Repaint
當(dāng)你移動DOM的位置,或是搞個(gè)動畫的時(shí)候。
當(dāng)你修改CSS樣式的時(shí)候。
當(dāng)你Resize窗口的時(shí)候(移動端沒有這個(gè)問題),或是滾動的時(shí)候。
當(dāng)你修改網(wǎng)頁的默認(rèn)字體時(shí)。
注:display:none會觸發(fā)reflow,而visibility:hidden只會觸發(fā)repaint,因?yàn)闆]有發(fā)現(xiàn)位置變化。
基本上來說,reflow有如下的幾個(gè)原因:
Initial。網(wǎng)頁初始化的時(shí)候。
Incremental。一些Javascript在操作DOM Tree時(shí)。
Resize。其些元件的尺寸變了。
StyleChange。如果CSS的屬性發(fā)生變化了。
Dirty。幾個(gè)Incremental的reflow發(fā)生在同一個(gè)frame的子樹上。
看幾個(gè)例子:
$("body").css("color", "red"); // repaint $("body").css("margin", "2px"); // reflow, repaint var bstyle = document.body.style; // cache bstyle.padding = "20px"; // reflow, repaint bstyle.border = "10px solid red"; // 再一次的 reflow 和 repaint bstyle.color = "blue"; // repaint bstyle.backgroundColor = "#fad"; // repaint bstyle.fontSize = "2em"; // reflow, repaint // new DOM element - reflow, repaint document.body.appendChild(document.createTextNode("dude!"));
當(dāng)然,我們的瀏覽器是聰明的,它不會像上面那樣,你每改一次樣式,它就reflow或repaint一次。一般來說,瀏覽器會把這樣的操作積攢一批,然后做一次reflow,這又叫異步reflow或增量異步reflow。但是有些情況瀏覽器是不會這么做的,比如:resize窗口,改變了頁面默認(rèn)的字體,等。對于這些操作,瀏覽器會馬上進(jìn)行reflow。
但是有些時(shí)候,我們的腳本會阻止瀏覽器這么干,比如:如果我們請求下面的一些DOM值:
offsetTop, offsetLeft, offsetWidth, offsetHeight scrollTop/Left/Width/Height clientTop/Left/Width/Height IE中的 getComputedStyle(), 或 currentStyle
因?yàn)椋绻覀兊某绦蛐枰@些值,那么瀏覽器需要返回最新的值,而這樣一樣會flush出去一些樣式的改變,從而造成頻繁的reflow/repaint。
Chrome調(diào)試工具查看頁面渲染順序頁面的渲染詳細(xì)過程可以通過chrome開發(fā)者工具中的timeline查看
發(fā)起請求;
解析HTML;
解析樣式;
執(zhí)行JavaScript;
布局;
繪制
頁面渲染優(yōu)化瀏覽器對上文介紹的關(guān)鍵渲染路徑進(jìn)行了很多優(yōu)化,針對每一次變化產(chǎn)生盡量少的操作,還有優(yōu)化判斷重新繪制或布局的方式等等。
在改變文檔根元素的字體顏色等視覺性信息時(shí),會觸發(fā)整個(gè)文檔的重繪,而改變某元素的字體顏色則只觸發(fā)特定元素的重繪;改變元素的位置信息會同時(shí)觸發(fā)此元素(可能還包括其兄弟元素或子級元素)的布局和重繪。某些重大改變,如更改文檔根元素的字體尺寸,則會觸發(fā)整個(gè)文檔的重新布局和重繪,據(jù)此及上文所述,推薦以下優(yōu)化和實(shí)踐:
HTML文檔結(jié)構(gòu)層次盡量少,最好不深于六層;
腳本盡量后放,放在前即可;
少量首屏樣式內(nèi)聯(lián)放在標(biāo)簽內(nèi);
樣式結(jié)構(gòu)層次盡量簡單;
在腳本中盡量減少DOM操作,盡量緩存訪問DOM的樣式信息,避免過度觸發(fā)回流;
減少通過JavaScript代碼修改元素樣式,盡量使用修改class名方式操作樣式或動畫;
動畫盡量使用在絕對定位或固定定位的元素上;
隱藏在屏幕外,或在頁面滾動時(shí),盡量停止動畫;
盡量緩存DOM查找,查找器盡量簡潔;
涉及多域名的網(wǎng)站,可以開啟域名預(yù)解析
總結(jié)瀏覽器渲染是個(gè)很繁瑣的過程,其中每一步都有對應(yīng)的算法。
了解渲染過程原理可以有針對的性能優(yōu)化,而且也可以懂得一些基本的要求和規(guī)范的原理。
最后文章中間很多語句都是直接復(fù)制的原文,自己的語言概況還是不及原文精彩。
《How Browser Work》
瀏覽器的工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘
瀏覽器渲染原理
淺析前端頁面渲染機(jī)制
瀏覽器 渲染,繪制流程及性能優(yōu)化
優(yōu)化CSS重排重繪與瀏覽器性能
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/112271.html
摘要:性能優(yōu)化網(wǎng)站的性能細(xì)線在幾個(gè)方面網(wǎng)站首頁加載速度動畫的流暢度通過分析瀏覽器的渲染原理資源對渲染的影響,得出優(yōu)化網(wǎng)站性能的辦法。查看性能的工具的面板錄制網(wǎng)頁加載的過程,分析記錄瀏覽器渲染過程中每個(gè)過程的耗時(shí)。通過引入,可以避免阻塞。 1 Web性能優(yōu)化 Web網(wǎng)站的性能細(xì)線在幾個(gè)方面: 網(wǎng)站首頁加載速度 動畫的流暢度 通過分析瀏覽器的渲染原理、資源對渲染的影響,得出優(yōu)化網(wǎng)站性能的辦法...
摘要:端優(yōu)談?wù)勱P(guān)于前端的緩存的問題我們都知道對頁面進(jìn)行緩存能夠有利于減少請求發(fā)送,從而達(dá)到對頁面的優(yōu)化。而作為一名有追求的前端,勢必要力所能及地優(yōu)化我們前端頁面的性能。這種方式主要解決了淺談前端中的過早優(yōu)化問題過早優(yōu)化是萬惡之源。 優(yōu)化向:單頁應(yīng)用多路由預(yù)渲染指南 Ajax 技術(shù)的出現(xiàn),讓我們的 Web 應(yīng)用能夠在不刷新的狀態(tài)下顯示不同頁面的內(nèi)容,這就是單頁應(yīng)用。在一個(gè)單頁應(yīng)用中,往往只有一...
摘要:不推薦移動端瀏覽器前端優(yōu)化策略相對于桌面端瀏覽器,移動端瀏覽器上有一些較為明顯的特點(diǎn)設(shè)備屏幕較小新特性兼容性較好支持一些較新的和特性需要與應(yīng)用交互等。 GitHub鏈接:https://github.com/zwwill/blo... 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展開,遇到不會不懂的點(diǎn)還請站外擴(kuò)展 開車...
摘要:不推薦移動端瀏覽器前端優(yōu)化策略相對于桌面端瀏覽器,移動端瀏覽器上有一些較為明顯的特點(diǎn)設(shè)備屏幕較小新特性兼容性較好支持一些較新的和特性需要與應(yīng)用交互等。 GitHub鏈接:https://github.com/zwwill/blo... 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展開,遇到不會不懂的點(diǎn)還請站外擴(kuò)展 開車...
摘要:不推薦移動端瀏覽器前端優(yōu)化策略相對于桌面端瀏覽器,移動端瀏覽器上有一些較為明顯的特點(diǎn)設(shè)備屏幕較小新特性兼容性較好支持一些較新的和特性需要與應(yīng)用交互等。 GitHub鏈接:https://github.com/zwwill/blo... 圍繞前端的性能多如牛毛,涉及到方方面面,以我我們將圍繞PC瀏覽器和移動端瀏覽器的優(yōu)化策略進(jìn)行羅列注意,是羅列不是展開,遇到不會不懂的點(diǎn)還請站外擴(kuò)展 開車...
閱讀 3715·2021-10-14 09:43
閱讀 3311·2021-08-25 09:38
閱讀 609·2019-08-30 15:55
閱讀 1343·2019-08-30 13:05
閱讀 2237·2019-08-29 16:05
閱讀 501·2019-08-29 12:58
閱讀 2791·2019-08-29 12:34
閱讀 3241·2019-08-26 12:15