A. 为什么每个前端开发者都要理解网页渲染
今天我要将关注点放到网页渲染以及其重要性上。虽然已经有很多文章提到过这个主题了,但大部分信息都是零碎的片段。为了思考这件事情,我需要研究很多信息的来源。这也就是为什么我觉得我应该写这篇文章的原因。我相信这篇文章对新手会很有用,并且对想刷新和巩固他们已经了解的东西的高手也同样适用。
渲染应该从最开始当页面布局被定义时就进行优化,样式和脚本在页面渲染中扮演着非常重要的角色。专业人员知道一些技巧以避免一些性能问题。
这篇文章不会深入研究浏览器的技术细节,而是提供一些通用的原则。不同浏览器引擎工作原理不同,这就使特定浏览器的学习更加复杂。
浏览器是怎样渲染一个页面的?
我们从浏览器渲染页面的大概过程开始说起:
由从服务器接收到的 HTML 形成DOM(文档对象模型)。
样式被加载和解析,形成 CSSOM(CSS 对象模型)。
紧接着 DOM 和 CSSOM 创建了一个渲染树,这个渲染树是一些被渲染对象的集合( Webkit 分别叫它们”renderer”和”render object”,而在Gecko 引擎中叫”frame”)。除了不可见的元素(比如 head 标签和一些有 display:none 属性的元素),渲染树映射了 DOM 的结构。在渲染树中,每一个文本字符串都被当做一个独立的 renderer。每个渲染对象都包含了与之对应的计算过样式的DOM 对象(或者一个文本块)。换句话说,渲染树描述了 DOM 的直观的表现形式。
对每个渲染元素来说,它的坐标是经过计算的,这被叫做“布局(layout)”。浏览器使用一种只需要一次处理的“流方法”来布局所有元素(tables需要多次处理)。
最后,将布局显示在浏览器窗口中,这个过程叫做“绘制(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 选择器的性能排行(从最快的开始):
ID选择器:#id
class选择器:.class
标签:div
相邻的兄弟元素:a + i
父元素选择器:ul > li
通配符选择器:*
伪类和伪元素:a:hover,你应该记住浏览器处理选择器是从右向左的,这也就是为什么最右面的选择器会更快——#id或.class。
div*{...}//bad
.listli{...}//bad
.list-item{...}//good
#list.list-item{...}//good
在你的脚本中,尽可能的减少 DOM 的操作。把所有东西都缓存起来,包括属性和对象(如果它可被重复使用)。进行复杂的操作的时候,最好操作一个“离线”的元素(“离线”元素的意思是与 DOM 对象分开、仅存在内存中的元素),然后将这个元素插入到 DOM 中
如果你使用 jQuery,遵循jQuery 选择器最佳实践
要改变元素的样式,修改“class”属性是最高效的方式之一。你要改变 DOM 树的层次越深,这一条就越高效(这也有助于将表现和逻辑分开)。
尽可能的只对 position 为 absolute 或 fix 的元素做动画。
当滚动时禁用一些复杂的:hover动画是一个很好的主意(例如,给 body 标签加一个 no-hover 的 class)关于这个主题的文章。
想了解更多的细节,可以看一下这些文章:
1. How browsers work
2. Rendering: repaint, reflow/relayout, restyle
希望这篇文章能够对你有所帮助!
原文链接:frontendbabel翻译:伯乐在线-Moejser
译文链接:http://blog.jobbole.com/72692/
B. 如何将js从数据库中渲染出来的数据做成table分页
您好
如果要在jsp页面里实现按你要求分页的话,你可以循环方式这样写
for(int i=初始纪录树;i<最大记录数;i++){
list.add(从数据库取出的又放进去的ArrayList<对象>);
}
之后在从list里取用循环取出并输出在前台页面。这里的初始记录数为(currentPage-1)*pageSize,这里的最大记录数为currentPage*pageSize。
每次请求都是该页面,而仅仅是***.jsp?currentPage=?这个问号不同而已。
当然不赞成把JAVA代码放在JSP页面,因为它仅仅是用来展示而尽量不要参与逻辑业务。要放在控制层或业务层。比如说去请求servlet。
并且一次取所有数据的分页并不适合当数据量很大的时候。可以使用数据库分页。如mysql 用top,oracle用rownum。
C. js 如何渲染从数据库中取到的文本,文本带有html标签,如果直接取到页面的话,标签都会显示
functionhtml2Escape(sHtml){
returnsHtml.replace(/[<>&"']/g,function(c){
return{'<':'<','>':'>','&':'&','"':'"',"'":'''}[c];
});
}
//其中{}是键值对的对象,c是属性,就是<>&"'这些,根据其中某个找到对应的html的字符
//html字符转义
D. 前端用js如何实现购物车功能,如图那样的效果
这是需要多个方法才能完成的
1,需要动态添加商品那一条显示的function
2,个数那个需要一个增加减少的function
3, 需要个统计总数量的
4,需要一个检测checkbox的
你做到什么程度了
E. 什么是前端渲染什么是服务端渲染两者区别及应用场景
举个商品列表页面为例子。
前端渲染:说的应该是刚进入页面时,商品列表这些数据都不给你,不会渲染出这些数据。然后加载script时,再用ajax或者fetch之类的发起了请求另一个接口,服务端返回了商品列表的json数据给你,你在js中用模板引擎之类的技术,把这些数据拼成html字符串插入到Dom里。
服务端渲染:服务端用php的smarty模板或者java的jsp,把页面的商品列表信息渲染出来了,返回一个html给浏览器了。
区别:如果页面要求被蜘蛛抓取,前端渲染的数据就不能被抓取到,但是服务端渲染的页面就能被抓取到。如果有SEO要求,只能用服务端渲染。如果用Node.js渲染的话,那就都没这些问题了。
F. js怎么吧集合渲染到表格中
具体思路,就是把集合的数据进行遍历,然后对应填充的表格中,或者说生成并填充到表格中
G. python如何爬取js渲染后列表
使用js渲染的列表优先查看是否能爬取js取得的数据源
若流量追踪无法检测到, 可以通过selenium等web自动化工具
若嫌弃这些工具太大, 可以用pyExecJs执行js
H. 怎样用vue.js和ajax实现商品列表的更新
Vue.js简介
vue是法语中视图的意思,Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API。
一、动态参数显示
ajax异步请求后,接收到返回的data参数并显示在前端
1.1 引入js,也加入了jQuery
<script type="text/javascript" src="/js/vue.min.js"></script> <script type="text/javascript" src="/js/jquery-2.1.3.js"></script>
1.2 html
<div id="app"> <p>{{ message }}</p> <button v-on:click="showData">显示数据</button> </div>
1.3 JS
注意:这里JS一定要放在$(function() {})里面,或者是写到body里面
new Vue({ el: '#app', data: { message: '' }, methods: { showData: function () { var _self = this; $.ajax({ type: 'GET', url: '...', success:function(data) { _self.message = JSON.stringify(data); } }); } } })
二、动态列表显示
开始展示一个空白列表,ajax异步请求后,接收到返回的data列表信息并显示
2.1 引入js,也加入了jquery
<script type="text/javascript" src="/js/vue.min.js"></script> <script type="text/javascript" src="/js/jquery-2.1.3.js"></script>
2.2 html
<div id="app"> <table> <thead> <tr> <th style='width:3%; text-align: left'>ID</th> <th style='width:5%; text-align: left'>名称</th> <th style='width:10%; text-align: left'>条形码</th> <th style='width:10%; text-align: left'>简称</th> </tr> </thead> <tbody> <tr v-for="goods in goodsList"> <td>{{goods.id}}</td> <td>{{goods.name}}</td> <td>{{goods.barcode}}</td> <td>{{goods.shortName}}</td> </tr> </tbody> </table> <button v-on:click="nameSearch()">查询</button><br><br> </div>
2.3 JS
var goodsVue = new Vue({ el: '#app', data: { goodsList : '' }, methods: { nameSearch: function () { var _self = this; $.ajax({ type: 'GET', url: '...', success:function(data) { _self.goodsList = data; } }); } } })
以上所述是小编给大家介绍的Vue.js Ajax动态参数与列表显示实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
I. 纯js在网页中渲染一个列表,列表中的数据用js定义一个数组,存储在数组中,至少要有两个字段,例如:
var data = [
{"id":"1","text":"姓名1"},
{"id":"2","text":"姓名2"}
]
var html = [];
html.push("<ul>")
for(var i=0,len=data.length;i<len;i++){
html.push("<li id="+data[i].id+">"+data[i].text+"</li>");
}
html.push("</ul>");
document.body.innerHTML = html.join("");
J. js大数据量如何实现页面的局部渲染(不是局部刷新)
不知道你所说的“实现局部渲染”是什么意思,
不就是加载时间太长了?
这里要优化的,肯定是你的js代码,
比如,尽量减少对document的操作次数(可组装成一条或几条记录后,再将生成的html添加到document,而不是一边组装一边添加)
另外可以对1000多条数据分页啊!