当前位置:首页 » 网页前端 » 前端渲染
扩展阅读
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的技术而不采用绝对定位等等,如果你能理解渲染的原理,就能从源头找到问题,然后制定自己的解决方案