MySQL索引使用方法和性能优化
关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型网站单日就可能会产生几十万甚至几百万的数据,没有索引查询会变的非常缓慢。还是以WordPress来说,其多个数据表都会对经常被查询的字段添加索引,比如wp_comments表中针对5个字段设计了BTREE索引。
一个简单的对比测试
以我去年测试的数据作为一个简单示例,20多条数据源随机生成200万条数据,平均每条数据源都重复大概10万次,表结构比较简单,仅包含一个自增ID,一个char类型,一个text类型和一个int类型,单表2G大小,使用MyIASM引擎。开始测试未添加任何索引。
执行下面的SQL语句:
1 |
mysql> SELECT id,FROM_UNIXTIME( time ) FROM article WHERE a.title= '测试标题' |
查询需要的时间非常恐怖的,如果加上联合查询和其他一些约束条件,数据库会疯狂的消耗内存,并且会影响前端程序的执行。这时给title字段添加一个BTREE索引:
1 |
mysql> ALTER TABLE article ADD INDEX index_article_title ON title(200); |
再次执行上述查询语句,其对比非常明显:
MySQL索引的概念
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。上述SQL语句,在没有索引的情况下,数据库会遍历全部200条数据后选择符合条件的;而有了相应的索引之后,数据库会直接在索引中查找符合条件的选项。如果我们把SQL语句换成“SELECT * FROM article WHERE id=2000000”,那么你是希望数据库按照顺序读取完200万行数据以后给你结果还是直接在索引中定位呢?上面的两个图片鲜明的用时对比已经给出了答案(注:一般数据库默认都会为主键生成索引)。
索引分为聚簇索引和非聚簇索引两种,聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。
MySQL索引的类型
1. 普通索引
这是最基本的索引,它没有任何限制,比如上文中为title字段创建的索引就是一个普通索引,MyIASM中默认的BTREE类型的索引,也是我们大多数情况下用到的索引。
01 |
–直接创建索引 |
02 |
CREATE INDEX index_name ON table ( column (length)) |
03 |
–修改表结构的方式添加索引 |
04 |
ALTER TABLE table_name ADD INDEX index_name ON ( column (length)) |
05 |
–创建表的时候同时创建索引 |
06 |
CREATE TABLE ` table ` ( |
07 |
`id` int (11) NOT NULL AUTO_INCREMENT , |
08 |
`title` char (255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , |
09 |
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , |
10 |
` time ` int (10) NULL DEFAULT NULL , |
11 |
PRIMARY KEY (`id`), |
12 |
INDEX index_name (title(length)) |
13 |
) |
14 |
–删除索引 |
15 |
DROP INDEX index_name ON table |
2. 唯一索引
与普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一,创建方法和普通索引类似。
01 |
–创建唯一索引 |
02 |
CREATE UNIQUE INDEX indexName ON table ( column (length)) |
03 |
–修改表结构 |
04 |
ALTER TABLE table_name ADD UNIQUE indexName ON ( column (length)) |
05 |
–创建表的时候直接指定 |
06 |
CREATE TABLE ` table ` ( |
07 |
`id` int (11) NOT NULL AUTO_INCREMENT , |
08 |
`title` char (255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , |
09 |
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , |
10 |
` time ` int (10) NULL DEFAULT NULL , |
11 |
PRIMARY KEY (`id`), |
12 |
UNIQUE indexName (title(length)) |
13 |
); |
3. 全文索引(FULLTEXT)
MySQL从3.23.23版开始支持全文索引和全文检索,FULLTEXT索引仅可用于 MyISAM 表;他们可以从CHAR、VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或CREATE INDEX被添加。////对于较大的数据集,将你的资料输入一个没有FULLTEXT索引的表中,然后创建索引,其速度比把资料输入现有FULLTEXT索引的速度更为快。不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。
01 |
–创建表的适合添加全文索引 |
02 |
CREATE TABLE ` table ` ( |
03 |
`id` int (11) NOT NULL AUTO_INCREMENT , |
04 |
`title` char (255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , |
05 |
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL , |
06 |
` time ` int (10) NULL DEFAULT NULL , |
07 |
PRIMARY KEY (`id`), |
08 |
FULLTEXT (content) |
09 |
); |
10 |
–修改表结构添加全文索引 |
11 |
ALTER TABLE article ADD FULLTEXT index_content(content) |
12 |
–直接创建索引 |
13 |
CREATE FULLTEXT INDEX index_content ON article(content) |
4. 单列索引、多列索引
多个单列索引与单个多列索引的查询效果不同,因为执行查询时,MySQL只能使用一个索引,会从多个索引中选择一个限制最为严格的索引。
5. 组合索引(最左前缀)
平时用的SQL查询语句一般都有比较多的限制条件,所以为了进一步榨取MySQL的效率,就要考虑建立组合索引。例如上表中针对title和time建立一个组合索引:ALTER TABLE article ADD INDEX index_titme_time (title(50),time(10))。建立这样的组合索引,其实是相当于分别建立了下面两组组合索引:
–title,time
–title
为什么没有time这样的组合索引呢?这是因为MySQL组合索引“最左前缀”的结果。简单的理解就是只从最左面的开始组合。并不是只要包含这两列的查询都会用到该组合索引,如下面的几个SQL所示:
1 |
–使用到上面的索引 |
2 |
SELECT * FROM article WHREE title= '测试' AND time =1234567890; |
3 |
SELECT * FROM article WHREE utitle= '测试' ; |
4 |
–不使用上面的索引 |
5 |
SELECT * FROM article WHREE time =1234567890; |
MySQL索引的优化
上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。下面是一些总结以及收藏的MySQL索引的注意事项和优化方法。
1. 何时使用聚集索引或非聚集索引?
动作描述 | 使用聚集索引 | 使用非聚集索引 |
列经常被分组排序 | 使用 | 使用 |
返回某范围内的数据 | 使用 | 不使用 |
一个或极少不同值 | 不使用 | 不使用 |
小数目的不同值 | 使用 | 不使用 |
大数目的不同值 | 不使用 | 使用 |
频繁更新的列 | 不使用 | 使用 |
外键列 | 使用 | 使用 |
主键列 | 使用 | 使用 |
频繁修改索引列 | 不使用 | 使用 |
事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。其实这个具体用法我还不是很理解,只能等待后期的项目开发中慢慢学学了。
2. 索引不会包含有NULL值的列
只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
3. 使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
4. 索引列排序
MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
5. like语句操作
一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
6. 不要在列上进行运算
例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。关于这一点可以围观:一个单引号引发的MYSQL性能损失。
最后总结一下,MySQL只对一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的like(不以通配符%或_开头的情形)。而理论上每张表里面最多可创建16个索引,不过除非是数据量真的很多,否则过多的使用索引也不是那么好玩的,比如我刚才针对text类型的字段创建索引的时候,系统差点就卡死了。
移动版专题设计的那些事
响应式设计是否适合于专题设计
tuntundeng:如今越来越多的移动设备出现在我们身边,作为设计师对网站专题的设计进入到一个新阶段,需要考虑更多的用户访问环境,输入设备,分辨率等不同因素。响应式网页是目前热门的解决方案,好比一双男生的休闲鞋,可以与所有裤子进行随意搭配。但是对于专题设计来说,响应式设计并不合适。
专题网页的设计通常是短平快,在特定时间达到一些运营需求。而响应式设计通常需要考虑更多不同分辨率下的响应效果,花费的设计和开发时间成本可能是double。而且专题设计具有很强的形式感,响应式设计的流体布局,必然会对视觉造成限制,所以对于专题来说做成响应式的网站需要慎重考虑。最高效的办法就是传统的为手机版单独做一版设计稿,让手机版网页满足通用的移动设备分辨率。
先做PC版的页面还是手机版页面
看用户的访问数据来定。一般情况下都是先做PC版的页面再做手机页面,PC端网页可以呈现更丰富的内容,用户浏览网页时更专注,达到最好的体验。但有很多情况下,页面的访问更多的来自手机端,比如手游的专题,用户通过微信、手Q入口进入。如果开始就先做PC版的专题,想必手机版的内容将是一个移植的PC版网页,让移动版的体验大打折扣。世界上最远的距离不是我在你身边却不知道我爱你,而是我用手机开你网页,你却你不知道。
酷跑的官网用户访问来源,超过80%来自移动端,在为酷跑的专题设计时则先从手机版开始设计。
举两个栗子,twitter与instagram的PC页面都是从手机端的延展,继承了手机端的交互,保持了一个很好的一致性体验。
手机版专题页面的注意事项
1. 安全宽度与扩展区域让页面适应主流分辨率
与PC上网页的做法一样,确定一个安全宽度,把重要信息控制在640PX宽度内(以iphone分辨率为安全宽度。目前手游手机版专题规范的数值如下,仅供参考:
目前主要浏览器在iphone4S下的首屏高度如下,可以根据具体页面投放的渠道做响应的首屏高度
2. 控制图片的大小
专题的头图一般有很强的视觉,对于手机用户来说,加载一张图片的等待时间比PC上成本大很多,如果一个页面加载时间超过5秒,70%的用户会选择关闭,那么再出彩的专题也没办法呈现再用户面前了,所以需要对设计稿做折中的处理。
在做头部的延展区域(超出640px范围),推荐使用纯色,渐变,可以平铺的素材,以便于减少头图的大小,提高加载速度,并且延展区域可以无缝连接。模糊的背景可以最大限度的压缩图片质量(反正是糊的,再怎么糊都可以)
3. 字体
手机中的字号一般上电脑中的两倍,一般在电脑中用的12px的字体在手机网页中就该使用24px。在设计的过程中,也要使用iOS和安卓默认渲染的字体,以便更真实的还原真实环境。
在规范手游移动版专题中,主要字号控制在3个,大中小都有一个区间。避免随意用字体字号,并且字号必须上整数。
4. 控件交互区域适合触控
手机专题的主按钮高度大于80px,并且根据活动的需求放在首屏内。文字链接上下的间距大于80px,手指在屏幕上热区最小感应是44px。
5. 移动端网页少用跳转
手机用户的网络环境不如PC用户,页面的跳转会对用户产生更大的心理效力,如果在手机页面中能吧信息合理的展示在一个页面中最佳。如果非要跳转,咱们可以用些假装不是跳转的方式,比如展开,浮出等。减少用户产生的不安全感。
移动专题也可以很出彩
虽然手机因为性能,网络等限制因素,不能达到PC专题那么优秀的效果。但手机网页还是有他独有的优势。
Wagerfield
手机网页也是可以动起来的,而且还可以通过手机特有的重力感应功能做视差滚动效果的交互,看起来很优雅。
Diplomatic-cover
通过手机控制PC页面的浏览也是一种新体验,不妨试试挖掘更多可能性,用户对新事物的接受程度没咱们想的那么低。
Infinityblade
无尽之剑的官网,手机版与PC版有很好的一致性。手机的手指滑动交互在这个页面中有很好的体验,并且动画效果很赞。
做手机网页的必备工具:PS PLAY
详细介绍戳这里《Ps Play——移动端预览Photoshop设计零阻力》
ISUX出品的工具,通过同一wifi可以同步电脑中的设计稿在手机中预览,快速检阅设计稿的真实环境效果,减少不必要的修改。
纵使手机本身的局限,使得咱们做手机网页的时候缩手缩脚,但手机的功能越来越强大,相信在不久之后,手机完全可以实现现在PC中的效果。网络环境也会越来越好,加载速度的加快也有利于设计师发挥更大的空间
原文地址:tgideas
作者: tuntundeng
PhantomJS-前端自动化测试 – 网易用户产品&前端群博客
前端自动化测试向来是一件很困难的事情,特别是涉及UI层面的测试时更是爱莫能助,目前还没有很成熟的Web UI层自动化测试方案,我们这时候就必须借助于很多第三方的工具。
PhantomJS便是这么一个为自动化而生的利器,它本质上是一个基于webkit内核的无界面浏览器,并可使用JavaScript或CoffeeScript进行编程。由于没有界面,它的使用就有点像curl, lynx之类的命令行式文本浏览器。但PhantomJS远不是文本浏览器那么简单,由于它是基于webkit内核的,因此拥有的完善的Javascript解析、页面渲染功能,你完全可用它来模拟一个现代浏览器在加载网页时所做的各种事件。
我们来看看PhantomJS能做的事件吧:
-
不借助于浏览器的前端测试,并支持Jasmine, Capybara, QUnit, WebDriver, YUI Test, BusterJS, FuncUnit, Robot Framework等诸多单元测试框架
-
页面操作,通过标准DOM API或借助jQuery库对页面进行修改
-
页面截图,甚至支持页面中的SVG和Canvas元素,可作为图片导出引擎,支持导出为pdf或png
-
网络测试,可轻松生成网络测试报告(HAR格式),用于绘制瀑布图
举例来说,比如我们希望将Canvas绘制的内容导出为png图片,这通过PhantomJS来做就再合适不过了。但首先你得编写Javascript操作脚本,下面是PhantomJS自带的一个demo( colorwheel.js):
var page =newWebPage;
page.viewportSize ={ width:400, height :400};
page.content ='<html><body><canvas id=”surface”></canvas></body></html>’;
page.evaluate(function(){
var el = document.getElementById(‘surface’),
context = el.getContext(‘2d’),
width = window.innerWidth,
height = window.innerHeight,
cx = width /2,
cy = height /2,
radius = width /2.3,
imageData,
pixels,
hue, sat, value,
i =0, x, y, rx, ry, d,
f, g, p, u, v, w, rgb;
el.width = width;
el.height = height;
imageData = context.createImageData(width, height);
pixels = imageData.data;
for(y =0; y < height; y = y +1){
for(x =0; x < width; x = x +1, i = i +4){
rx = x – cx;
ry = y – cy;
d = rx * rx + ry * ry;
if(d < radius * radius){
hue =6*(Math.atan2(ry, rx)+Math.PI)/(2*Math.PI);
sat =Math.sqrt(d)/ radius;
g =Math.floor(hue);
f = hue – g;
u =255*(1- sat);
v =255*(1- sat * f);
w =255*(1- sat *(1- f));
pixels[i]=[255, v, u, u, w,255,255][g];
pixels[i +1]=[w,255,255, v, u, u, w][g];
pixels[i +2]=[u, u, w,255,255, v, u][g];
pixels[i +3]=255;
}
}
}
context.putImageData(imageData,0,0);
document.body.style.backgroundColor =’white’;
document.body.style.margin =’0px’;
});
page.render(‘colorwheel.png’);
phantom.exit();
我们只需执行 phantomjs colorwheel.js,便可按自定义的canvas操作得到最终的图片,如下:
如果我们只是想截图,那就更简单了,phantomJS同样提供了一个demo脚本:rasterize.js,我们只要执行:
phantomjs rasterize.js http://raphaeljs.com/polar-clock.html clock.png
便可轻松得到:
再看看怎么做简单的页面测试,比如只想知道一个页面的总加载时间(包括下载所有静态资源、页面渲染),可简单地使用自带的pagetest.js
phantomjs loadspeed.js http://auto.163.com/special/browserupgrade/
得到结果如下:
Page title is 低版本IE升级提示
Loading time 1147 msec
够简单吧,如果你想进一步做网页性能分析,得到资源加载的详细瀑布图,phantomJS还可以为你生成HAR(HTTP Archive)报表。同样借助一下自带的netsniff.js:
photomjs netsniff.js http://auto.163.com/special/browserupgrade/
将生成的json格式报告放到HAR viewer( http://www.softwareishard.com/har/viewer/ )中,便可轻松得到资源加载瀑布图:
事实上,phantomjs自带的用例就有近40个,好好挖掘一下,你肯定能得到意想不到的惊喜,如果你想要做单元测试,那就更要潜心研究一下了:http://code.google.com/p/phantomjs/
Backbone案例的初略理解
http://juntype.com/junlab/99.html
最近发现自己越来越不行了,做前端也有些岁月了,神马HTML5,CSS3等层出不穷,如果再不及时Update一下自己,很快也会被这个行业给淘汰了!废话不多说了,今天主要是记一下自己学习Backbone的笔记。
国内有用到这技术的有豆瓣说 阿尔法城 可能是他们比较出名。。。
前端MVC 主要讲的是在前端方面实现MVC的模板,在前端也有自己的模块,视图,控制器,这结合RESTful来做是个不错的选择,我在瘦服务端架构TSA(Thin Server Architecture)记录了一下
而Backbone只是通向前端MVC其中的一条路而已。。。
Backbone.js API中文文档
我下面的源码出自 让我们用Backbone.js来写一个HelloWorld程序 我也是通过这源码结合API进行学习 上面那篇博文有些错误,我已经修正。
这里说一下Backbone的执行顺序
路由(Backbone.Router)-> 模型(Backbone.Model)-> 视图(Backbone.View)
路由告诉你要去哪里。
App.Controllers.Routes = Backbone.Router.extend({ routes: { "!/hello" : "hello",//使用#!/hello驱动路由 这里会去分行下面hello这个函数 }, hello : function(){ //新建一个模型,模型向后端请求更新内容成功后根据模型渲染新页面 var helloModel = new App.Models.Hello; //调用模板 helloModel.fetch({ success: function(model){ //成功拿到数据,调用视图渲染页面 var helloView = new App.Views.Hello({model: model}); helloView.trigger('change'); //绑定change事件 } }); } });
模型告诉该干些什么。这里是去拿数据,set是提供一个设置初始数据
App.Models.Hello = Backbone.Model.extend({ url: function() { return '/index/test'; // 获得数据的后台地址。 }, initialize: function() { this.set({'message':'hello world'}); // 前端定义一个message字段,name字段由后端提供。 } });
最后你就知道了有什么了
App.Views.Hello = Backbone.View.extend({ el: "body", //在哪里显示 template: $("#hello-container-template").html(), //获取模板 模板是用Mustache initialize: function(options){ this.options = options; this.bind('change', this.render); this.model = this.options.model; }, render: function(){ // render方法,目标只有两个:填充this.el,返回this以便链式操作。 $(this.el).html(Mustache.to_html(this.template,this.model.toJSON())); return this; } });
上面就是MVC的核心了,下面就是一个管理着 视图/控制/模型 的全局类
var App = { Models: {}, Views: {}, Controllers: {}, Collections: {}, initialize: function() { new App.Controllers.Routes(); Backbone.history.start() // 要驱动所有的Backbone程序,Backbone.history.start()是必须的。 } };
调用,完事啦。。。
App.initialize();
其实我只知道了这么点皮毛,接下来就要在实践中多去学习了,期待有后续。。。
给自己加个油,提个醒!
PS 接下来,我将试着在 doulaipk.com 去实践,求PHP程序猿.
nginx根据host判断root的 with passenger配置
server { server_name ~^(.*\.)?(?<app>[^.]+)\.dev$; root /opt/apps/$app/public; rails_env development; passenger_enabled on; }
Nginx 0.8.25+ 应该都能用,参考 server_name
需要跑哪个Rails/Rack app就在/opt/apps下面建立个symbol link (link到含config.ru的根目录)
cd /opt/apps ln -s /path/to/myapp
当然http里需要设置下passenger_root
和passenger_ruby
。
www.myapps.dev 和 myapps.dev 都会访问 /opt/apps/myapp
如果你连/etc/hosts都不想改,想像pow那样,在 Mac 下可以用这个脚本来启动pow里的DNS server
Linux有Hoof可以用(我还没试过),使用nsswitch来自动把指定的根域名解析到本机
github更新自己fork的代码,从原作者分支更新代码
github上有个很方便的功能叫fork,将别人的工程一键复制到自己账号下。这个功能很方便,但有点不足的是,当源项目更新后,你fork的分支并不会一起更新,需要自己手动去更新。下面记录下网上找到的更新的方法
1、在本地装好github客户端,或者git客户端
2、clone 自己的fork分支到本地,可以直接使用github客户端,clone到本地,如果使用命令行,命令为:
git clone git@github.com:break123/three.js.git three.js
3、增加源分支地址到你项目远程分支列表中(此处是关键),命令为:
git remote add mrdoob git://github.com/mrdoob/three.js.git
此处可使用git remote -v查看远程分支列表
4、fetch源分支的新版本到本地
[master]> git fetch mrdoob
5、合并两个版本的代码
[master]> git merge mrdoob/master
6、将合并后的代码push到github上去
[master]> git push origin master
Zepto 使用中的一些注意点
前段时间完成了公司一个产品的 HTML5 触屏版,开发中使用了 Zepto 这个著名的 DOM 操作库。
为什么不是 jQuery 呢?因为 jQuery 的目标是兼容所有主流浏览器,这就意味着它的大量代码对移动端的浏览器是无用或者低效的。
而 Zepto 只针对移动端浏览器编写,因此体积更小、效率更高,更重要的是,它的 API 完全仿照 jQuery ,所以学习成本也很低。
但是在开发过程中,我发现 Zepto 还远未成熟,其中包含了一些或大或小的“坑”,与 jQuery 的差距还是很明显的,所以写篇文章记录下,希望对后来者有帮助
注意,本文撰写时 Zepto 版本为 1.0 正式版
从哪里下载 Zepto
这个问题看起来很蠢,从官网下载不就行了嘛!可是你有没有发现下载链接上面有行小字呢?
There are more modules; a list of all modules is available in the README.
在这个 README 里面你会惊奇地发现,Zepto 源码中有 14 个模块,而官网提供的标准版里面只有 7 个模块!而且居然不包含对移动端开发非常重要的 touch 模块(提供对触摸事件的支持)!
所以我的建议是,不要从官网下载,而是从 Github 下载了源代码之后自己 Build 一个版本,这样你可以自行挑选适合的模块。比如我挑选的模块是这么几个:
- polyfill,zepto,detect,event,ajax,form,fx 这7个就是标准版包含的模块
- fx_methods 有了这个模块之后,.show() .hide() 等几个方法才能支持动画了,比如
.show('fast')
- data 提供对 .data() 方法的完整支持,像 jQuery 一样用内存对象存储
- assets 移除 img 元素后做一些特殊处理,用来清理内存
- selector 更多的选择器的支持,后面会提到
- touch 对触摸事件的支持,比如 tap 事件
如果你对 Node 不了解不知道如何 Build 的话,可以下载我的版本
不要用 click 事件,用 tap 代替
这个估计已经广为人知了,因为 click 事件有 200~300 ms 的延迟,为了更快的响应,最好用 Zepto 提供的 tap 事件
不相信的话,可以用以下代码测试一下
var t1,t2; $('#id').tap(function () { t1 = Date.now(); }); $('#id').click(function () { t2 = Date.now(); alert(t2 - t1); });
Zepto 对 CSS 选择器的支持
郑重提醒,:text :checkbox :first
等等在 jQuery 里面很常用的选择器,Zepto 不支持!
原因很简单,jQuery 通过自己编写的 sizzle 引擎来支持 CSS 选择器,而 Zepto 是直接通过浏览器提供的document.querySelectorAll
接口。
这个接口只支持标准的 CSS 选择器,而上面提到的那些属于 jQuery 选择器扩展,所以仔细看看这个网页,注意一下这些选择器。
当然也有好消息,就是上面提到的 selector 模块,如果有这个模块的话,能够支持 部分 的 jQuery 选择器扩展,列举如下:
- :visible :hidden
- :selected :checked
- :parent
- :first :last :eq
- :contains :has
元素的尺寸计算
首先 Zepto 没有 .innerHeight() .outerWidth() 等四个方法,其次,它的 .height()/.width() 方法也不完善,对于display:none
的元素,计算出的高宽都是 0
而这在 jQuery 里面是没有问题的,因为 jQuery 针对这种元素,会先设置其 css 样式设置为position: "absolute", visibility: "hidden", display: "block"
计算完高宽后再恢复,参见 https://github.com/jquery/jquery/blob/master/src/css.js#L460
如果遇到这种特殊情况,可以参考 jQuery 写一个类似的方法
.prop() 方法的陷阱
有次我要把一个文本框置为只读,写了这么一行 $('#text').prop('readonly', true)
结果死活不工作
找了半天才发现,正确的写法是这样 $('#text').prop('readOnly', true)
,如果你居然看不出两者的差别,那么悄悄提示你:注意大小写!
翻了一下相关的文档,原来只读属性的正确拼法确实是 readOnly,可是在 jQuery 里面上一段代码却能正常工作
于是到 jQuery 源码里面一找才发现,还有这么一段https://github.com/jquery/jquery/blob/master/src/attributes.js#L466
jQuery.each([ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() { jQuery.propFix[ this.toLowerCase() ] = this; });
从这里也能看到,jQuery 的成熟度真是难以超越,因为他把我们都惯坏了……
考虑到这段代码比较简单,我厚颜无耻地抄袭了一下然后给 Zepto 提了一个 pull request ,如果你们喜欢这种无脑的用法,可以去评论表达支持(记得用英文)
2013-11-25 这个 PR 已经被 Merge
.show() 的动画效果
如果没有 fx_mehods 模块的话,.show() 方法是不支持动画的,不过有了这模块后,动画的支持还是有点小问题,比如这么一段 HTML
<div style="background:black;opacity:0.7;display:none"> test </div>
如果你调用 $('div').show('fast')
,那么动画完成后你看到的不会是一个半透明的元素,而是全黑不透明的
因为 Zepto 的 .show() 动画实现的很简单,没有高宽的变化,而是将透明度从 0 逐渐变为 1,所以元素上原来设置的透明度就被替代了。
这种情况下,可以用 .fadeIn() 方法来替代 .show()
结语
看到这里相信你已经了解为什么我说” Zepto 还远未成熟“,目前它其实还仅仅处于“能用”,远未达到 jQuery “好用”的地步
最后,关于整个 HTML5 触屏版的前端开发,我有篇 Slide 做了总结,本文只是其中关于 Zepto 部分的详细阐述,感兴趣的可以去看看
http://chaoskeh.com/blog/some-experience-of-using-zepto.html
2010 Web前端技术趋势及总结 Facebook摘全明星MVP
导读:经过这段时间国内(百度,淘宝,新浪等)及国外(Facebook,Youtube,Yahoo等)各大公司的集中自曝,我们可以从中总结出 2010 Web前端技术的一些趋势。总的来说,随着后端技术(存储,并发,分布式)的成熟,各大公司已经把重点从后端架构调整/建设转移至前端(TTI时间,快速发布,带宽利用率)。
作为明星技术的HTML 5/CSS 3,都未正式成为各公司的考虑重心,虽有所尝试,但在关键功能上,均未成为主力。这也W3C对当前HTML 5/CSS 3标准现状的表述:“不适宜用作生产环境”一致。
Web前端技术的范围
1. 编程语言/技术(HTML,JavaScript,CSS等)
2. 跨浏览器兼容性/支持(JS Framework,CSS Library)
3. 网络传输性能(并行下载,带宽利用率)
4. 浏览器渲染时间/性能(TTI即用户可交互前等待时间,JS执行性能)
个人感觉,Facebook无疑又成为了技术上的明星,在大家还在感慨其对于PHP的重大改进HipHop(Blocked inside China mainland)的时候,今年Facebook又在前端技术方面给大家带来了惊喜。
Facebook面临的问题
500M(Million)注册用户,50%每天至少访问一次,用户平均每日在线时间为5小时25分钟。带宽及服务器压力均很大。
Facebook的解决方案
Quickling
Facebook提出了一个新名词Ajaxify,顾名思义,就是将传统的POST/GET转换为Ajax请求。优点显而易见,首先减少了不必要的 HTML传输,只请求和渲染页面需要更新的部分,这就相应减少了所需传输的内容加快了内容送达至用户的时间。并且也减少了服务端对HTML的不必要的渲染。Facebook也提到了可以减少session的重复load/unload。
使用Ajax也许不是什么新鲜的新闻,大家拒绝这项技术的原因可能很大程度基于SEO的需求。解决方案也很简单,将Ajax只是作为提高用户体验的手段,而不是浏览网站必须的方法,即可解决SEO的问题(P.S. Facebook不需要SEO)。
整套方案包括:Link Controller, HistoryManager, BootLoader, Busy Indicator, CSS Unloading, Permanent link support, Resetting timer functions。这些方案本身没有什么特殊的,大部分都可以顾名思义,需要解释一下的可能是link controller,其含义是将标准的HTML LINK请求转换为Ajax请求(通过绑定click事件)。Facebook的可贵之处是提供了这一整套完整的解决方案,最大程度上保证了网站的可用性。
效果:
提高了10%-30%的网站传输时间,并提高了20%-30%的服务端页面渲染速度。
使用范围:
45%的Facebook页面使用了此项技术。
PageCache
简单的说,就是将访问过的页面缓存在客户端。但我们知道,作为Facebook这样交互性很强的网站,需要保障用户能尽早的获得更新后的信息,而不是给用户展示一个毫无意义的过期页面。
Facebook设计了一个框架来识别一个页面是否来自于缓存(猜测:页面首次加载完毕后将所有Ajax的Callback和Result缓存在本地。Facebook页面是基于Ajax获取页面内容),若来自于缓存,通过Ajax来更新所需更新的模块(猜测:通过JavaScript预先定义本页面所需更新的div Id及对应的callback handler,并在页面下载时同时下载下来)。
其提到了三种更新类型:增量更新,用户复写(例如用户在页面上回复了一则评论)及跨页更新(例如在消息详细页面将一则消息标识为已读,需将首页的未读消息数进行更新)。核心思路还是依据Ajax进行更新。具体思路为:
增量更新:只要页面来自于缓存,即更新所有预定义的需增量更新的模块。
用户复写:通过HistoryManager记录用户操作并在cache页面读取后重放所有被标记为“replayable”的操作。
跨页更新:通过服务端Database API发送信号至客户端将过期缓存标识为invalid(不清楚如何实现。也许是DB端提供一个开放的webservice,客户端通过Ajax持续访问此API来获得此信息)。获得了缓存过期信号后,通过Ajax更新需要更新的信息。
Facebook顺带提到了一个更新Ajax内容避免页面变化/闪烁的小技巧,就是先将需更新的地方设置为blank,而非直接更新其内容。
效果:
加速了10倍的网站响应时间并节约了20%的服务端页面渲染成本。
BigPipe
此项技术通过将页面分割为各个Pagelets的方式,将整张页面的获取/渲染变成了并行的方式(感觉非常像iframe sets,但Facebook使用Ajax实现。)。此项技术是Quickling和PageCache的基石。此技术包含了服务端/客户端两方面,在前后端均打破了以往页面的渲染形式。
实现细节:
Pagelet的Response为JSON格式,包括id,css,js,content,onload等属性及相应内容,收到后会通过预定义好的JS function来进行渲染。
Pagelet提供的高级功能:Pagelet的继承,Phased Rendering(猜测:依据规则渲染,也就是依据Pagelet的Response进行渲染),跨Pagelet依赖(数据依赖,显示依赖,JS依赖)。
BigPipe的三种模式:
◆一次渲染模式:即普通模式,支持搜索引擎,用来支持那些不支持JS的客户端。
◆管线模式:即并行模式,并行请求,并即时渲染。
◆并行模式:并行请求,但在获得所有请求的结果后再渲染。
效果:
提高了2倍的页面响应时间。
扩展阅读:世界最大的PHP站点 Facebook后台技术探秘
YouTube面临的问题
每天2Billion的访问。每分钟上传35小时的内容。可YouTube需要即时播放视频!越快越好。
YouTube解决方案
1. 将JavaScript引用位置从页首移至页尾。
2. 直接嵌入Flash Player(YouTube之前使用JS来加载Flash Player)。通过页尾的JS来判断客户端的Flash版本(或不支持Flash),来替换预先嵌入的Flash Player或内容(如果需要的话),用来支持特定的客户群。
效果:页面渲染时间从~400ms降低为~200ms。Flash播放时间从~1200ms降低为~1100ms。
3. 预加载视频连接: 通过使用JavaScript创建Image引用视频内容来与解析DNS并预开启一个connection供之后使用。
效果:建立视频连接的总时间从~260ms降低为~180ms。
4. 提供简化版:这个很无聊,就是提供一个简版。
效果:页面加载时间从~1750ms降低为~1100ms。
5. UIX Widget系统:延迟加载非关键内容。其实整段没什么新意,大部分省略,无非是通过Ajax在页面渲染完后再来动态加载非关键内容。比较特别的是利用 JS的事件冒泡,在最上层用一个handler来处理各种事件(优点不详。。也许只是代码比较简洁集中吧),通过CSS来标识和识别对应的 handler。
Yahoo Mail
Yahoo如何构建下一代的Mail系统?答案就是通过YUI3。Yahoo的技术绝对是最优的,其已经将Web前端技术发展到一个非常成熟的地步,照顾到Web的方方面面(数据压缩,模块化,高效CSS,非阻碍式JavaScript加载,静态内容提供,利用浏览器Cache等等),所以也鲜有创新了。某种程度上来说,Facebook的一些所谓创新也不过是后知后觉,Yahoo早已考虑并实现了这些方案,只是也许不是那么有针对性而已。
Baidu
感觉整体倾向于组织结构介绍及一些比较过时的内容。
Taobao
还在讨论一些何时使用Ajax,何时不使用的问题。
相反的,淘宝的精益测试倒是引起了我的兴趣,出自微软的淘宝员工鹤云讲述了淘宝是如何进行CI(持续集成)的。有一些经验例如代码覆盖率测试也给人一些启发。
新浪博客
也是一些组织架构,开发方式的内容。介绍了一下新浪自己的JavaScript框架。并无太多亮点。
大概就总结了这么多吧,感觉还是国外在主导。国内也在越来越重视这个方向,一些有实力的企业也做出了一些成绩,但还是与国际潮流有差距,也许是重视程度的区别吧。欢迎大家补充讨论。
交互体验优化:4步让移动网站看起来像本地应用
译自:
A Beginner’s Guide to Perceived Performance: 4 Ways to Make Your Mobile Site Feel Like a Native App
原作者:Kyle leads
译者: TAT.sheran
注:该文章大约3000字。它覆盖了移动端网页交互体验优化的很多不同方面的实际解决方案,用来优化你的网页运行速度。注意不是让你的站点运行的有多快,而是让你的用户感觉有多快。
当下在移动端构建一个优秀的网站逐渐变得越来越简单。无论是响应式设计还是自适应式,只要清楚你要做的样式,精心制作一个好看的站点就不是什么问题。
也许你的用户和我们一样,想要一个像本地应用体验的网站,所以构建这样的体验将会带来很大的挑战。
大多数时候,当人们说一个应用就像一个原生程序或者像本地应用,他们并不是在讨论这个网站的外观。相反,他们讨论的是当他们做出的一些操作之后的响应效果。
本地应用相对于Web应用要快得多,动画效果渲染也更加平滑;当点击按钮时,按钮自身会立即响应变化的样式,不管操作是否加载成功,都不会报错。
使你的站点看起来想本地应用,意味着要尽一切可能的方法使你的站点快速的响应。
当今,性能优化是一个非常热门的话题。最近,网站开发已经越来越重量级,网页越重代表运行得越慢,所以有人声称做一个高性能的网页应用程序几乎是不可能的。
这就是为什么Facebook不得不转向本地应用的原因。因为从目前所拥有的Web资源来看,并不能达到他们期望的运行速度和交互体验。
尽管Facebook也这么认为,但是构建一个高性能的网站还是有可能的。虽然并不容易,但还是在我们可控制的范围内。我们只是需要花更多的精力去将它实现而已。从技术上说,我们有能力使我们的网站运行地更快,看上去更现代化,以及拥有更完美的交互体验。
体验性能 VS 实际性能
虽然提高实际性能很重要,但这并不意味着用户最终能够感觉到改善。
年初在西雅图的一次An Event Apart会议中,Luke Wroblewski 讲述了下关于他们的移动应用Polar。他阐述到他和他的团队非常努力地优化每次加载新的选票所需时间。
于此同时,当发送加载选票的异步请求时,他们用了一个轻量的微调控件提示用户。但是用户反馈在加载新的选票时显示微调控件让他们感觉比以前慢了好多,尽管实际上它比以前更快。Polar迅速发布了一个版本移除了这个微调控件,然后用户马上就觉得页面加载快了好多。
这个例子能很好的说明用户对性能感知的重要性。你的网站是否真正运行非常快并不重要。就像这个微调控件的例子,它只是吸引了用户的注意力,但事实上仍然让用户感觉在等待响应,而正确的做法是,我们应该去分散用户的注意力。
作为设计师和开发者,我们的目标不仅仅是从学术理论上创造一个快速的站点,而更应该从体验上去创造一个最快的站点。
用户是如何感知你的站点的运行速度才是最重要的,任何实际速度的提升不过是一个已经精心装饰好的蛋糕外帽。我认为体验性能优化比实际性能优化更重要,但绝不代表不应该去做实际性能优化。
综上所述,你该做些什么来优化你站点的体验性能呢?
这里有四个技巧,你可以立即开始实施。
1. 给你的按钮增加触摸状态
在移动设备上改善网站体验性能最容易的方法之一就是使用激活状态。
众所周知,用户在任何时候点击你网页上的按钮,在网页响应前他都必须等待约300毫秒。
浏览器会保持这个延时,这样它才能确保用户并不是想做其它动作(准确地说就是双击)。所以浏览器在这三分之一秒内检测用户是否有其它操作,如果没有,则响应用户上一次点击。当这个事件最终发生时,它会给出一个灰色的高亮展示给用户。
这是一个糟糕的体验,Nielsen团队进行了一项调查,结果显示任何超过100毫秒的响应都会让用户感到他们在等待——而用户想要的仅仅是浏览你的网页。
然而大多数的移动站点,包括我自己创建的,并没有应用这个体验设计,设计师们总是使用链接或者按钮的默认触摸状态。
要使你的站点感觉快,就要让你的按钮能够及时响应用户的点击事件,并且在状态改变时给用户一个可见的反馈。
有一个非常好用的CSS伪类叫做 active 状态,它可以用来在网页上显示一个按钮或者链接被点击了。我们也可以同时把它使用在PC端浏览器上。
不幸的是,无论是iOS还是Android上的链接或者按钮被点击的时候都会忽略这个属性。为了使用这个active状态,你需要使用JavaScript给页面添加一个简单的事件:
document.addEventListener("touchstart", function(){}, true)
这样,你就可以使用CSS来给按钮添加active状态或者移除点击高亮的状态了:
-Webkit-tap-highlight-color: rgba(0,0,0,0);
给你创建的按钮添加了这些属性和active状态之后,用户就可以立即感觉到页面的反馈,即使实际上真实的反馈速度并没有改变。你只是让用户针对自己的行为得到了一个及时的反馈,而不是让他们等待300毫秒后才看到页面响应。
如果你想要使页面立即响应,你可以做进一步的改进。
使用一个fasttap或者fastclick函数,可以完全消除点击按钮时300毫秒的延时,与active状态搭配使用,可以让你的站点拥有飞一般的速度。
关于更多fasttap的信息,可以参考谷歌的这篇文章 this article by Google 或者Github上的一个现成的实现this repo on Github。
2. 使用默认滚动
你曾经是否尝试在自己的站点上创建一个可滚动的容器,或者被一个运行起来非常慢,并且没有任何响应的滚动条困住?
幸运的是,Android 3+ 和iOS 5+ 都实现了一个新的名叫overflow-scroll的属性,用来开启原生的滚动条,它运行起来非常完美。
这个滚动条使用起来就像是使用本地程序的感觉,实际上它就是原生的,你需要做的只是给你的滚动容器添加这个属性:
-Webkit-overflow-scrolling: touch;
然而,关于这个属性还存在一个问题,那就是当滚动到页面最顶部的时候会禁止你的iphone显示状态栏。这个BUG已经存在有段时间了,即使是最新版本iOS7上的移动版Safari都没有解决这个问题。
解决这个问题的方法之一是:创建一个类来给容器添加 overflow-scrolling:touch属性。然后只有当容器处于可见状态 时,使用JavaScript去应用这个类,使其生效。
在Android 4上你不需要这个属性,因为每个可滚动的容器都包含了原生滚动条。
在比较老的Android版本下,你有两个选择方案。我最喜欢的一个方法是检测容器是否支持滚动溢出属性来判断是否支持原生滚动。如果不支持,有几个JavaScript库可以用来代替,Filament Group’s Overthrow 和 iScroll 都是很不错的实现方案。
3. 创建高性能动画
在Web网站和本地应用之间最显著的差别是动画的使用。
多年前,本地应用在当今设备中就能够充分利用硬件图形加速。而在Web端,开发者却只能基于JavaScript来实现动画,对于移动端功能比较弱的CPU来说,运行起来会比较慢。
但是现在,随着移动浏览器的支持,我们可以大量利用CSS3动画来实现硬件加速。
这是一个英明的方法来添加那些我们喜欢的,本地应用都已经炫耀了多年的动画特效。
如果还是觉得不够快?要让Web动画感觉像本地动画,你必须确保你的动画运行起来不会慢或者足够稳定,这些都是相当困难的。
Allen Pike of Steamclock Software(一家软件公司) 2011年发表了一篇很赞的文章,大意为给用户提供一个有趣的不影响性能的动画,可以使用户对这个应用有一个非常好的印象。
有趣的是,这篇文章是关于本地应用开发的,但我们可以参考这篇文章用来在网页站点上创建类似本地应用的动画。
在这篇文章中,他描述了一个他所谓的“时间感知”:
1.动画的帧数至少要有60fps。这意味着每帧最起码都要在16毫秒内完成,这样才能让人感觉动画是原生的或者是平滑的。所有iOS的内置动画都保持在60fps的运行速度,这就是为什么在iPhone设备上滚动的感觉明显比Android设备好的原因(虽然谷歌最近在这个领域取得了很大的改善)。你应该确保所有跟用户有直接交互的动画都保持在这个速度才行。
2.所有事件的响应都应该保持在100毫秒以内。如果超过这个心理门槛,用户就会有慢的感觉,反之任何低于100毫秒的响应对用户来说都是一瞬间的体验。
3.如果一个动画一定需要超过100毫秒,那也至少要保证在1000毫秒内完成。Allen认为任何需要在这么长时间的行为都需要给用户一个反馈,比如一个进度控件或者一个滚动条。
但是正如我们前面介绍的Polar的例子,转移用户注意力实际上是弊大于利的。稍后我们将介绍一个不同的方法来处理这个问题。
4.任何一个超过1秒的响应都是不好的,并且需要谨慎。
当创建一个网站的时候,你还不得不考虑动画运行时间,知道这一切之后是否有种想转行的冲动?
不要担心,有些很好的资源可以使这些东西变得容易得多。
首先,有一个基于HTML5的一个CSS库,叫做Effeckt.css。这个库的目的是创建一个公用的动画,它们的帧数都处于60fps。虽然这个库还没有完全完成,但是库里的很多动画都已经可以很好的运行了,我们强烈推荐使用这个库来满足你们的项目需求。
另外一个非常好用的库就是Adobe公司的前端团队开发的Topcoat库,这是一个以性能为中心的CSS组件库,这个库里全是能够运行得非常顺畅的组件。因为动画性能是他们的主要目标,组件的每一部分,你都可以看到它究竟是如何执行的。
Topcoat和Effeckt.css可以结合一起使用,Topcoat可以直接使用Effeckt.css的功能,并且可以很完美的融合在一起。
接下来,我们来讨论前面提到的尽可能避免spinners问题的方法。
我的首选方法是避免spinners的等待时间不会超过100毫秒,但对于小于250毫秒的等待我会(使用spinner实际上是弊大于利的)用一个动画来隐藏它。
例如,你正在异步拉取一段内容的时候,尝试使用动画让容器缩上去,再缩回来以适应新的内容。这样一个简短的动画可以分散用户注意力,而不是盯着一个spinner,他们只需等待一个很短的动画完成。甚至他们都不知道是否有新的内容。
当然,那些重复且需要花费长时间完成的动画有可能让人觉得厌烦,所以一定要确保有节制的使用这些技术,对于大多数的动画而言这都是一个很好的建议。
4. 手势利用
本地应用优于Web应用的优势在于他们能够利用手势,对于使用触摸屏幕的用户来说,这样能够更加友好。
移动开发者已经意识到手势的魅力所在,并很快就使其得到了很好的利用。
看看类似Mailbox 或者Clear这样的例子,这些应用都使用了简单的手势,充分发挥了移动设备最大的优势——能够直接触摸屏幕的能力。
大多数网站都只会使用手势点击来触发事件,设计师甚至不想去实现其它手势,这样给用户像一个二等公民待遇的感觉。
我们开始考虑直接为这些设备开发特定的网站。如果用户的设备支持手势功能,那么为什么不利用他们呢?
当然,移动操作系统都存在一个问题那就是:劫持在浏览器中的手势,而去执行系统自身的响应。
对于本地应用,比如Facebook 使用屏幕左右边缘的滑动开拓导航。然而不幸的是,对于Web应用来说,这种行为叫出界,Chrome会使用这个操作来切换选项卡,新版本的iOS7的Safari浏览器却会使用它来历史前进和后退。
好把,这些手势还是有相当多的限制的,究竟哪些可供我们使用呢?这里有4个:
手势1 一侧到另一侧的滑动
即使即将出界,一侧到另外一侧的滑动也是一个相当不错的手势,只是需要注意的是不要太靠近屏幕的边缘了。
手势2 拉取刷新
拉取刷新是让用户去获取数据的另外一个手势,有一大堆JavaScript库可以很简单的去实现这个手势,有一个我以前用过的库叫Hook.js。
手势3 长按
有一个很有用的属性叫做 –Webkit-touch-callout: none; 它将关闭移动端Safari默认的长按事件,但是你想要在Android上关闭它还需要额外的工作。
长按手势主要用于拖动一个元素(比如重排一个列表的顺序)或者展示更多操作给用户(例如,社交分享)。
手势4 缩放功能
每个人都理解缩放,大多数人在网站上看到一个照片的时候都会去缩放来查看更多细节。
有时候浏览器也会劫持这种手势,即使这样,也没有那么糟糕。
无论是否需要锁定整个窗口的放大或者缩小,有时你也并不希望用户去缩放整个页面。为了接管这些多点触摸,你可以使用一个非常轻量库叫Hammer.js,这个库里有一堆手势,你可以使用内置的手势,也可以创建你自己的。
这有一个很优秀的图片缩放示例网站 imgur.com mobile Website,它能够检测你的触摸方法。
但是要注意的是,如果你使用了一个手势,请确保它是一个让用户感觉自然或有意义的行为。
总结
但愿有那么一天,我们不需要再区分本地应用还是Web应用。虽然这一天还没达到,但只要我们一直努力,使我们的网站让用户感受到是为他们量身打造,我相信那天一定会很快到来。
我觉得专注性能优化虽然是件好事,但我们也必须记住,我们的用户不是机器。
他们不关心你的网站发出了多少请求,也不在乎你的屏幕渲染得有多快。他们只关心网站带给他们体验上的感觉。
重要的是如何让你的网站看起来或者感觉上是最快的。那些用户无法感知的高速网站是毫无意义的。
如果你有更多提高体验性能的建议,请在评论中发表。