當前位置:首頁 » 網頁前端 » 前端渲染
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

前端渲染

發布時間: 2022-02-10 11:08:51

前端.什麼是頁面渲染&影響渲染速度的兩個

什麼是渲染
頁面渲染引擎的基本操作,簡單而言是從一個網頁的Url開始,根據Url所對應的網頁各項資源,輸出可視化的結果的過程;
影響渲染速度的兩個因素
repaint(重繪)
如果只是改變某個元素的背景色、文 字顏色、邊框顏色等等不影響它周圍或內部布局的屬性,譬如background-color(背景色), border-color(邊框色), visibility(可見性),將只會引起瀏覽器 repaint(重繪)。repaint 的速度明顯快於 reflow(在IE中例外,reflow 要比 repaint 更緩慢)。
reflow(迴流)
說到頁面為什麼會慢?那是因為瀏覽器要花時間、花精力去渲染,尤其是當它發現某個部分發生了點變化影響了布局,需要倒回去重新渲染, 該過程稱為reflow(迴流)。
reflow 幾乎是無法避免的。現在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯 示與隱藏)等,都將引起瀏覽器的 reflow。滑鼠滑過、點擊……只要這些行為引起了頁面上某些元素的佔位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲 染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響著。

㈡ 前端渲染和後端渲染的區別 及適用場景

前端渲染沒有後台渲染的功能強。但是前端渲染不佔用伺服器的資源,也不佔用網路。

㈢ 前端如何把後端渲染好的html頁面直接顯示出來

如果是ajax獲取的,直接塞到指定的dom結構裡面就可以了呀

㈣ 後台只提供json數據,頁面全靠前端渲染,交互,需要用到哪些框架,有

dojo可以做到,並且特別好用。希望採納。放一個例子給你看看。
使用很簡單:
<!-- 顯示待辦視圖 -->
<xsl:variable name="todoRequestUrl">http://xxxx.xxxx.xxxx.xxxx/public/tcwmain.nsf/AG_GetUndo_Mobile?OpenAgent&UserName=<xsl:value-of select="$DaiBanUserName"/>&temp</xsl:variable>
<div
data-dojo-type="moa/TodoScrollableView"
id="todoPage"
data-dojo-props="
requestData:'{$todoRequestUrl}',
labelName:'待辦文件',
heading:'todoHeading',
refresh:'todoRefresh',
fixedHeader:'todoHeading'
"
>
<!--
<div data-dojo-type="dojox/mobile/Heading" data-dojo-props="label:'待辦工作',fixed:'top'" id="todoHeading">
<span data-dojo-type="dojox/mobile/ToolBarButton" style="float:left" data-dojo-props="moveTo:'homePage'">首 頁</span>
<span data-dojo-type="dojox/mobile/ToolBarButton" style="float:right" id="todoRefresh">刷 新</span>
</div>
-->
<div data-dojo-type="dojox/mobile/Heading" data-dojo-props="label:'待辦文件',fixed:'top'" id="todoHeading">
<span
data-dojo-type="dojox/mobile/ToolBarButton"
style="float:left"
data-dojo-props="moveTo:'documentSystemPage',clickable:true,onClick:onHomeReturnClick"
>返 回</span>
<span data-dojo-type="dojox/mobile/ToolBarButton" style="float:right" id="todoRefresh">刷 新</span>
</div>
<xsl:call-template name="homeMainNavy"/>
</div>
/*
*可以自動載入數據列表的視圖
*數據結構與待辦相同的模塊使用這個視圖,非同步載入數據
*這事類對象,需要new關鍵字或直接用標簽調用
*/
define([
"dojo/_base/declare",
"dojo/request",
"dojo/store/Memory",
"dojo/_base/array",
"dojox/mobile/EdgeToEdgeStoreList",
"dojox/mobile/ScrollableView",
"dojox/mobile/ContentPane",
"./html5-session-store",
"dojo/dom",
"dojo/dom-attr",
"dojo/on",
"dojo/touch",
"./mdp-common",
"./dojo-ready-task",
"./rootUrl",
"dojo/string",
"./mdpServlet",
"dojo/date",
"dojo/date/stamp",
"dojo/topic",
"./dialog"

],function(
declare,
request,
Memory,
arrayUtil,
EdgeToEdgeStoreList,
ScrollableView,
ContentPane,
session,
dom,
domAttr,
on,
touch,
mdpCommon,
task,
rootUrl,
strUtil,
mdpServlet,
dojoDate,
dojoStamp,
topic,
dialog

){
var DataScrollView = declare([ScrollableView],{
count:0,
maxCount:100,
requestUrl:mdpServlet,
requestData:null,
labelName:"",
heading:"",
refresh:"",
progress:null,
list:null,
sessionName:function(){
var session = "globle."+this.get("id");
return session;
},

postCreate:function() {
this.inherited(arguments);
//給自定義view載入數據
this._loadData();

var self = this;
var refresh = dom.byId(this.refresh);
this.own(
on(refresh,touch.release,function(evt){
session.remove(self.sessionName());
self._loadData();
evt.preventDefault();
evt.stopPropagation();
})
);
},

//更新首頁待辦導航列表視圖數值
_publishInform:function(count)
{
topic.publish("moa/home/listcreated",{id:this.id,sessionName:this.sessionName()});
},

_loadData:function() {
//使用緩存
if(session.support()) {
var response = session.getJson(this.sessionName());
if(!!response) {
this._createList(response);
this._publishInform();
return;
}
}

//使用ajax載入
if(!this.requestUrl) {
return;
}

var self = this;
//發ajax請求,火狐會存在問題,初步估計問題是重定向造成的
request(this.requestUrl,{
method:"POST",
data:{url:this.requestData},
handleAs:"json"
}).then(function(response){
self._sort(response);
//使用session保存數據
if(session.support()) {
session.saveJson(self.sessionName(),response);
}
self._createList(response);
self._publishInform();
},function(ex){
});
},

_setHeading:function() {
var heading = dom.byId(this.heading);
if(!heading) {
return;
}
var label = this.labelName;
var style = "position:relative;top:-3px;margin-left:10px;color:red;border-radius:30px;border:1px solid #f9f9f9;padding:3px 6px;font-size:13px;";
var count = Math.min(this.count,this.maxCount);
label = label +"<span style='"+style+"'>共"+ count +"條</span>";
task.setHeadingLabel(label,this.heading);
},

//給列表排序
_sort:function(data)
{
if(!data || !data.data || data.data.length < 2) {
return;
}
//排序函數
var compare = function(a,b)
{
if(!a.rightText || !b.rightText)
{
return 0;
}

return dojoDate.difference(dojoStamp.fromISOString(a.rightText),dojoStamp.fromISOString(b.rightText),"day")
}

data.data.sort(compare);
},

_createList:function(data){
if(!!this.list){
this.list.destroy();
}
this.count = !data || !data.data?0:data.data.length;
if(this.count === 0 || !!data.data && data.data.length === 0) {
var pane = new ContentPane({content:"暫無數據",style:"width:100%;padding:15px 0;text-align:center;line-height:200%;color:red;font-weight:bold;"});
this.list = pane;
task.addViewChild(this,pane);
return;
}
var model = !data.data?{data:[],idProperty:this.label}:{data:data.data,idProperty:this.label};
var store = new Memory(model);
var self = this;

this._setHeading();

var list = new EdgeToEdgeStoreList({
store:store,
postCreate:function() {
var children = this.getChildren();
arrayUtil.forEach(children,function(item){
item.clickable=true;
item.onClick=function(evt){

evt.preventDefault();
evt.stopPropagation();
//loadadd 1028
//this.set("busy",true);
//self._requestTodo(this.moaUrl)
//console.log("loading1......");
/*
dialog.progressIndecator();

var OADocUrl = this.moaUrl;
//必須0.2s後
var timeout = window.setTimeout(function(){window.clearTimeout(timeout);self._showContent(OADocUrl);},1000);
*/
self._showContent(this.moaUrl);

//self._updateTodoList(this.moaUrl);
};
})
}
});
task.addViewChild(this,list);
this.list=list;
},

_showContent:function(url) {
//記錄一個臨時cookie,這是返回主頁的時候用的,需要定位到主頁特定視圖
var newUrl = strUtil.trim(url)+"&todo";

if(this.id === "inReadingPage") {
this._updateTodoList(newUrl);
}
session.saveString("homeShowId",this.id);
//調用眾望的介面直接打開html頁面
var ObjForm = mdpCommon.GetForm("frm");
mdpCommon.InputField("frm","url",newUrl);
mdpCommon.AccessURL(ObjForm);
ObjForm.submit();
},

//更新待辦列表
_updateTodoList:function(url) {
var regExp = /([0-9A-Za-z]{32})/gi;
var result = url.match(regExp);
var unid;
if(!!result) {
unid=result[0];
}
if(!unid) {
return;
}

var todoList = session.getJson("globle."+this.id);
var count = todoList.count;
var todoList = todoList.data;

for(var i=0,len=todoList.length;i<len;i++){
var moaUrl = todoList[i].moaUrl.toUpperCase();

if(moaUrl.indexOf(unid) > -1) {
todoList.splice(i,1);
count--;
break;
}
}

session.saveJson("globle."+this.id,{count:count,data:todoList});
},

_cacheDocUrl:function(todoUrl,docUrl) {
if(!session.support()) {
return;
}
var todoUnid = this._getTodoUnidFromUrl(todoUrl);
session.saveString(this.sessionName()+"."+todoUnid,docUrl);
},

_getDocUrl:function(todoUrl){
if(!session.support()) {
return;
}
var todoUnid = this._getTodoUnidFromUrl(todoUrl);
return session.getString(this.sessionName()+"."+todoUnid);
},

_getTodoUnidFromUrl:function(todoUrl){
//從todo url中解析todo unid
var reg = /([A-Fa-f0-9]{32})/;
var res = reg.exec(todoUrl);
if(!!res){
return res[0].toUpperCase();
}
},

_requestTodo:function(url) {
var docUrl = this._getDocUrl(url);
if(!!docUrl){
this._showContent(docUrl);
return;
}
var self = this;
request(this.requestUrl,{
method:"POST",
data:{url:url},
handleAs:"json"
}).then(function(response){
docUrl = rootUrl+"/"+response.dbname+"/0/"+response.unid+"?editdocument";
self._cacheDocUrl(url,docUrl);
self._showContent(docUrl);
},function(ex){
});
}
});
return DataScrollView;
});

㈤ 為什麼每個前端開發者都要理解網頁渲染

今天我要將關注點放到網頁渲染以及其重要性上。雖然已經有很多文章提到過這個主題了,但大部分信息都是零碎的片段。為了思考這件事情,我需要研究很多信息的來源。這也就是為什麼我覺得我應該寫這篇文章的原因。我相信這篇文章對新手會很有用,並且對想刷新和鞏固他們已經了解的東西的高手也同樣適用。


渲染應該從最開始當頁面布局被定義時就進行優化,樣式和腳本在頁面渲染中扮演著非常重要的角色。專業人員知道一些技巧以避免一些性能問題。

這篇文章不會深入研究瀏覽器的技術細節,而是提供一些通用的原則。不同瀏覽器引擎工作原理不同,這就使特定瀏覽器的學習更加復雜。



瀏覽器是怎樣渲染一個頁面的?


我們從瀏覽器渲染頁面的大概過程開始說起:

  1. 由從伺服器接收到的 HTML 形成DOM(文檔對象模型)。

  2. 樣式被載入和解析,形成 CSSOM(CSS 對象模型)。

  3. 緊接著 DOM 和 CSSOM 創建了一個渲染樹,這個渲染樹是一些被渲染對象的集合( Webkit 分別叫它們」renderer」和」render object」,而在Gecko 引擎中叫」frame」)。除了不可見的元素(比如 head 標簽和一些有 display:none 屬性的元素),渲染樹映射了 DOM 的結構。在渲染樹中,每一個文本字元串都被當做一個獨立的 renderer。每個渲染對象都包含了與之對應的計算過樣式的DOM 對象(或者一個文本塊)。換句話說,渲染樹描述了 DOM 的直觀的表現形式。

  4. 對每個渲染元素來說,它的坐標是經過計算的,這被叫做「布局(layout)」。瀏覽器使用一種只需要一次處理的「流方法」來布局所有元素(tables需要多次處理)。

  5. 最後,將布局顯示在瀏覽器窗口中,這個過程叫做「繪制(painting)」。




重繪


當在頁面上修改了一些不需要改變定位的樣式的時候(比如background-color,border-color,visibility),瀏覽器只會將新的樣式重新繪制給元素(這就叫一次「重繪」或者「重新定義樣式」)。



重排


當頁面上的改變影響了文檔內容、結構或者元素定位時,就會發生重排(或稱「重新布局」)。重排通常由以下改變觸發:

· DOM 操作(如元素增、刪、改或者改變元素順序)。

·內容的改變,包括 Form 表單中文字的變化。

·計算或改變 CSS 屬性。

·增加或刪除一個樣式表。

·改變」class」屬性。

·瀏覽器窗口的操作(改變大小、滾動窗口)。

·激活偽類(如:hover狀態)。



瀏覽器如何優化渲染?


瀏覽器盡最大努力限制重排的過程僅覆蓋已更改的元素的區域。舉個例子,一個 position 為 absolue 或 fixed 的元素的大小變化隻影響它自身和子孫元素,而對一個 position 為 static 的元素做同樣的操作就會引起所有它後面元素的重排。

另一個優化就是當運行一段Jjavascript 代碼的時候,瀏覽器會將一些修改緩存起來,然後當代碼執行的時候,一次性的將這些修改執行。

舉例來說,這段代碼會觸發一次重繪和一次重排:


var$body=$('body');

$body.css('padding','1px');//重排,重繪

$body.css('color','red');//重繪

$body.css('margin','2px');//重排,重繪

//實際上只有一次重排和重繪被執行。


如上面所說,訪問一個元素的屬性會進行一次強制重排。如果我們給上面的代碼加上一行讀取元素屬性的代碼,這個情況就會出現:

var$body=$('body');

$body.css('padding','1px');

$body.css('padding');//這里讀取了一次元素的屬性,一次強制重排就會發生

$body.css('color','red');

$body.css('margin','2px');


上面這段代碼的結果就是,進行了兩次重排。因此,為了提高性能,你應該講讀取元素屬性的代碼組織在一起(細節的例子可以看JSBin上的代碼)。


有一種情況是必須觸發一次強制重排的。例如:給元素改變同一個屬性兩次(比如margin-left),一開始設置100px,沒有動畫,然後通過動畫的形式將值改為50px。具體可以看例子,當然,我在這里會講更多的細節。

我們從一個有transition的CSS class開始:

.has-transition{

-webkit-transition:margin-left1sease-out;

-moz-transition:margin-left1sease-out;

-o-transition:margin-left1sease-out;

transition:margin-left1sease-out;

}


然後進行實現:


//我們的元素默認有"has-transition"屬性

var$targetElem=$('#targetElemId');


//刪除包含transition的class

$targetElem.removeClass('has-transition');

//當包含transition的class已經沒了的時候,改變元素屬性

$targetElem.css('margin-left',100);


//再將包含transition的class添加回來

$targetElem.addClass('has-transition');


//改變元素屬性

$targetElem.css('margin-left',50);


上面的實現沒有按照期望的運行。所有的修改都被瀏覽器緩存了,只在上面這段代碼的最後才會執行。我們需要的是一次強制重排,我們可以通過進行以下修改來實現:


//刪除包含transition的class

$(this).removeClass('has-transition');


//改變元素屬性

$(this).css('margin-left',100);


//觸發一次強制重排,從而使變化了的class或屬性能夠立即執行。

$(this)[0].offsetHeight; //offsetHeight僅僅是個例子,其他的屬性也可以奏效。


//再將包含transition的class添加回來

$(this).addClass('has-transition');


//改變元素屬性

$(this).css('margin-left',50);


現在這段代碼如我們所期望的運行了。



實際的優化建議


匯總了一些有用的信息,我建議以下幾點:

·創建合法的 HTML 和 CSS ,別忘了制定文件編碼,Style 應該寫在 head 標簽中,script 標簽應該載入 body 標簽結束的位置。

·試著簡化和優化 CSS 選擇器(這個優化點被大多數使用 CSS 預處理器的開發者忽略了)。將嵌套層數控制在最小。以下是 CSS 選擇器的性能排行(從最快的開始):

  1. ID選擇器:#id

  2. class選擇器:.class

  3. 標簽:div

  4. 相鄰的兄弟元素:a + i

  5. 父元素選擇器:ul > li

  6. 通配符選擇器:*

  7. 偽類和偽元素:a:hover,你應該記住瀏覽器處理選擇器是從右向左的,這也就是為什麼最右面的選擇器會更快——#id或.class。

    div*{...}//bad

    .listli{...}//bad

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

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

  8. 在你的腳本中,盡可能的減少 DOM 的操作。把所有東西都緩存起來,包括屬性和對象(如果它可被重復使用)。進行復雜的操作的時候,最好操作一個「離線」的元素(「離線」元素的意思是與 DOM 對象分開、僅存在內存中的元素),然後將這個元素插入到 DOM 中

  9. 如果你使用 jQuery,遵循jQuery 選擇器最佳實踐

  10. 要改變元素的樣式,修改「class」屬性是最高效的方式之一。你要改變 DOM 樹的層次越深,這一條就越高效(這也有助於將表現和邏輯分開)。

  11. 盡可能的只對 position 為 absolute 或 fix 的元素做動畫。

  12. 當滾動時禁用一些復雜的:hover動畫是一個很好的主意(例如,給 body 標簽加一個 no-hover 的 class)關於這個主題的文章。


想了解更多的細節,可以看一下這些文章:

1. How browsers work

2. Rendering: repaint, reflow/relayout, restyle

希望這篇文章能夠對你有所幫助!


原文鏈接:frontendbabel翻譯:伯樂在線-Moejser

譯文鏈接:http://blog.jobbole.com/72692/

㈥ 什麼是前端渲染什麼是服務端渲染兩者區別及應用場景

舉個商品列表頁面為例子。
前端渲染:說的應該是剛進入頁面時,商品列表這些數據都不給你,不會渲染出這些數據。然後載入script時,再用ajax或者fetch之類的發起了請求另一個介面,服務端返回了商品列表的json數據給你,你在js中用模板引擎之類的技術,把這些數據拼成html字元串插入到Dom里。
服務端渲染:服務端用php的smarty模板或者java的jsp,把頁面的商品列表信息渲染出來了,返回一個html給瀏覽器了。
區別:如果頁面要求被蜘蛛抓取,前端渲染的數據就不能被抓取到,但是服務端渲染的頁面就能被抓取到。如果有SEO要求,只能用服務端渲染。如果用Node.js渲染的話,那就都沒這些問題了。

㈦ web前端渲染還是後端渲染,你傾向於哪個

看數據量,就像分頁一樣,數據量到達一定數量級就需要後台做物理分頁,數據量小的話就是邏輯分頁。
渲染也是有著異曲同工之妙,看渲染的具體情況而定,不能統一概論

㈧ web數據是前端渲染還是後端渲染好

前端渲染的話可以讓後台更專注業務數據處理,同時伺服器壓力也要小得多。但是如果你的項目需要讓搜索引擎索引,則最好不要使用前端渲染,因為現在的搜索引擎對前端框架不是特別支持,而且前端使用js對數據進行渲染,使得瀏覽器兼容性成為一個特別棘手的問題,如果你的項目不用管瀏覽器兼容性的話這就不是什麼問題。但是前端渲染使得前後端開發分離,可以提高開發效率,前端可以不用去處理後台的東西了,同時也可以減少網路帶寬的佔用。後台渲染就是伺服器壓力山大,畢竟需要將數據和模版渲染成頁面,不過這個可以使用緩存解決,同時因為後台渲染需要後台開發的知識,所以前端做好頁面之後還要由後台程序員進行修改才能使用,所以開發效率要低得多。後台渲染好頁面之後前端拿來直接就能展示,所以後台渲染可以支持更低版本的瀏覽器。

㈨ 如何區分一個網頁的內容是前端非同步渲染的還是後端直接返回的

右鍵查看源碼 , 就可以看出是前段渲染 ,還是後端渲染 (如頁面上的數據源碼都有則服務端渲染反之前端渲染)

㈩ 前端常識:為什麼每個前端開發者都要理解頁面的渲染

瀏覽器實質只是一個載入器
假設你要做性能優化,那麼DOMContentLoaded就必須提前,這樣可以讓操作優先進行,lazyload就是利用的這種原理

假設你要做樣式優化,那麼你不懂頁面渲染流程的話,是先讀背景還是先執行腳本
如果不知道頁面的渲染的話,你就不知道浮動元素是再渲染還是跟著標簽解析的時候同時繪制,一些老瀏覽器的兼容性為啥要用類似負margin的技術而不採用絕對定位等等,如果你能理解渲染的原理,就能從源頭找到問題,然後制定自己的解決方案