Schopenhauer说过这样的话:要估定人的伟大,则精神上的大和体格上的大,那法则完全相反。后者距离愈远即愈小,前者却见得愈大。
正因为近则愈小,而且愈看见缺点和创伤,所以他就和我们一样,不是神道,不是妖怪,不是异兽。他仍然是人,不过如此。但也惟其如此,所以他是伟大的人。
战士战死了的时候,苍蝇们所首先发见的是他的缺点和伤痕,嘬着,营营地叫着,以为得意,以为比死了的战士更英雄。但是战士已经战死了,不再来挥去他们。于是乎苍蝇们即更其营营地叫,自以为倒是不朽的声音,因为它们的完全,远在战士之上。
的确的,谁也没有发见过苍蝇们的缺点和创伤。
然而,有缺点的战士终竟是战士,完美的苍蝇也终竟不过是苍蝇。
去罢,苍蝇们!虽然生着翅子,还能营营,总不会超过战士的。你们这些虫豸们!
——鲁迅《华盖集》
战士和苍蝇
GoDaddy视频教程
Ubuntu下的郑码
最近360和QQ大战,打算重新到转Ubuntu上,但输入法却是个大问题。因为我用的是郑码输入法,这个输入法虽说装机率最高,每个中文Windows都会安装,但使用者却非常少,以至于Ubuntu就忽视了郑码,当然这里面也有版权的问题。
以前我记得Heiher曾经发布过Ubuntu郑码,但现在找到的链接都已经失效了。后来又找到Heiher的网站,终于在上面问到了最新的下载地址,最新的下载地址是:http://heiher.info/sftp/ime/zhengma/,当前最新版是ibus-table-zhengma_1.1.0.20091105-1_all.deb,也可以在极点郑码上面找到这款软件。在安装后重启Ubuntu就能在输入法栏中找到郑码了。在这里非常感谢Heiher给郑码爱好者带来这款软件。
另外还有一种在Ubuntu安装郑码的方法,不过有点麻烦,我没有试过,感兴趣的话可以看这两篇文章:《ibus郑码可以单独安装了》和《ubuntu 9.10 ibus 1.2安装郑码成功》。
CSS渲染开销真地非常大
《高性能网站建设进阶指南》中说处理CSS是最大的开销,我起先认为有点言过其实,最近才发现真是真理。
近期做的一个页面,要显示近200多行数据,每行数据里面有11个单元格,而每行的最后两个单元格中还嵌套有表格。这个页面突然最近两天变地非常慢,而且在IE6下尤为明显。刚开始以为是JavaScript的问题,就一直在这方面做优化。为了让页面看起来快点,我甚至用了分时分段创建DOM的做法,但情况仍然没有明显地好转。后来才发现其实创建DOM的过程是非常快的,而慢就慢在了渲染上面。我把CSS文件移除后页面变地非常快,最终在CSS文件中一句句地排查,终于找到了罪魁祸首:背景图片(background-image)。
原来设计要为每个单元格增加一个1像素的边框,并且每个单元格有固定的宽度,而加了一个边框的单元格在不同的浏览器下面它们最终的宽度就不一样。为了兼容我去掉了边框,改用了设置一像素平铺背景来模拟边框。表格有200多行,每行连子表格共有17个单元格,合在一起有3,4000个单元格,每个单元格都有平铺的小背景,不慢才怪!
这件事给我的教训很大,以前对CSS的认识不足,只关注JavaScript,现在要重新认识CSS了。
《高性能网站建设进阶指南》中给出了几条编写高效CSS选择符的要点:
- 避免使用通配符:除了传统意义上的通配选择符外,Hyatt把相邻兄弟选择符、子选择符、后代选择符和属性选择符都归纳到了“通配符”分类下,他仅推荐使用ID、类、和标签选择符。
- 不要限定ID选择符;对于
div#idsel这样的选择符,应该改成#idsel,因为在页面里一个指定的ID只能对应一个元素,没有必要再添加其它限定符。 - 不要限定类选择符:不要用具体的限定类选择符,如
li.mystyle,改成.list-mystyle会更好些 - 让规则越具体越好:如
ul li a这样的,最好是创建一个像.list-link这样的类。 - 避免使用后代选择符:通常使用后代选择符的开销是最高的,在有条件的情况下可以用子选择符代替。这一条对IE6无用,IE6不支持子选择符。
- 避免使用标签和子选择符:如果有像
#myid > li > a这样的选择符,可以改成一个类,如.myid-link。 - 质疑子选择符的所有用途:再次提醒检查所有使用子选择符的地方,然后尽可能用具体的类取代它。
- 依靠继承:了解哪些属性可能通过继承来获取,避免对这些属性重复指定规则,可以参考《Full property table》。
这些要点有很多不现实的地方,因为子选择符在实际操作中是必须要用到的,但是我们可以在达到效果的基础上利用这些要点来优化CSS代码。
这里有两篇Jon Sykes的文章,里面列出了不同规则对于渲染速度的影响,可以参考下:
此外,还在网上收集了一些CSS优化的规则,也列出来:
- 十六进制的颜色值对位数与大小写:建议用
#FFFFFF,而不要用简写#fff,因为十六进制的颜色值默认标准是大写及6位数标注,在未知情况下不希望冒险而降低了渲染的效率。 - 用display与visibility隐藏的差异:建议用
display:none来隐藏元素,display隐藏对象不保留物理空间,visibility为隐藏对象保留占据的物理空间。当浏览器渲染被占据的物理空间时,会有所消耗资源。 - border:none;与border:0;的区别:建议用
border:none;,和display与visibility的关系类似,分别不保留与保留空间。更多的是border:0;尽管可以隐藏掉边框,但它会为你保留border-color/border-style的使用权。 - 不宜过小的背景图片平铺:不赞成宽高8px以下的平铺背景图片。
- IE的滤镜:不建议使用IE的滤镜,不仅消耗资源,也有兼容问题。
NetTuts上的PHP操作SQLite代码
本来已经有了一篇《用php操作sqlite3》,但最近在NetTuts的《Creating a Web Poll with PHP》一文中发现了另一种SQLite的操作方法,虽然都是在用PDO,但是具体的步骤却不一样,方法更加兼容全面。大部分用法都和《用php操作sqlite3》基本相同,现在就列出更新和查找数据库的代码:
/* 更新数据 */
try{
$dbh = new PDO('sqlite:voting.db');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// 准备
$sth = $dbh->prepare("INSERT INTO tally (QID,AID,votes) values (:QID, :AID, 1)" );
// 插入新代码
$sth->execute(array('vote1',1));
$sth->execute(array('vote2',2));
}catch(PDOException $e){
// 23000错误代码表明 关键字已经存在了
if($e->getCode() == 23000){
try{
// 更新数据,并把 votes 加 1
$sth = $dbh->prepare( "UPDATE tally SET votes = votes+1 WHERE QID=:QID AND AID=:AID");
$sth->execute(array('vote1',1));
}catch(PDOException $e){
$this->db_error($e->getMessage());
}
}else{
$this->db_error($e->getMessage());
}
}
/* 获得信息 */
try{
// 准备
$STH = $dbh->prepare('SELECT AID, votes FROM tally WHERE QID = ?');
// 执行查找
$STH->execute(array('vote1'));
}catch(PDOException $e){
// 如果发生错误,直接返回一个空值
return array(0);
}
// 如果查找的数据不为空,逐行显示
while($row = $STH->fetch()){
$results[$row['AID']] = $row['votes'];
echo $row['votes'];
}
还有一篇《Introduction to PHP PDO》的文章,全面介绍PDO与PostgreSQL、SQLite、MySQL、Firebird、Informix、Oracle、ODBC、DBLIB、IBM DB2的连接,几乎包括了所有PHP能连的数据库了。
JavaScript压缩工具
JavaScript压缩工具很多,常用的可能就是YUICompressor、Closure Compiler、Packer,但我最常用的还是YUICompressor。
YUICompressor
YUICompressor是建立在rhino interpreter基础上的,所以它的特点就是安全。YUICompressor是用Java编写的,要运行它首先要配置好Java环境。YUICompressor的压缩内容如下:
- 移除注释
- 移除额外的空格
- 细微优化
- 标识符替换(Identifier Replacement)
使用YUICompressor的命令行代码如下:
java -jar yuicompressor-x.y.z.jar myfile.js -o myfile-min.js --charset utf-8
YUICompressor在压缩时还能够自动检查JS代码是否有错误,如果有错误它会列出错误的行数和原因。更难得的是,它也可以压缩CSS文件,对于前端人员简直就是一把多功能的瑞士军刀。
淘宝UED部把YUICompressor封装成了TBCompressor,这里有篇《TBCompressor介绍》,使用TBCompressor更加简单快捷。
Closure Compiler
Closure Compiler是Google公司公布的一款JS压缩工具,和YUICompressor相比,它的压缩率稍微高点,只是稍微,但对代码的准确率要求更高点。这里有一篇LifeSinger整理的《Closure Compiler vs YUICompressor》,讲述了两者的异同,可以做为选择的一个参考。
Closure Compiler使用的命令行代码如下:
java -jar compiler.jar --js hello.js --js_output_file hello-compiled.js
Closure Compiler还不仅提供了一个网络版可以直接在网页上压缩,而且还开放了API,你可以用HTML、Python或者其它语言文件调用这个API来压缩JS文件。
Packer
Packer是目前压缩率最高的JavaScript压缩工具,由Dean Edwards创建的。压缩后的JavaScript文件相当于一个ZIP文件,在执行的时候能够自动解压。不过带来的副作用就是对于编写不严格的代码,压缩时会出错,可以在压缩前用JSMin检查下。虽然Packer压缩后的代码在执行时先要自解压下,会降低执行效率,但对于大型文件来说,Packer的压缩率通常能达到50%,因而能加快下载速度。
Packer不仅有网页版,还有.NET、perl和PHP版。
Pro HTML5 Programming
《Pro HTML5 Programming》已经可以在网上下到PDF版的了,有兴趣可以去下载来研究下。
里面的内容也很丰富,介绍了HTML5的新元素和API,如下:
- Canvas API
- Audio and Video
- Geolocation API
- Communication APIs
- WebSocket API
- Forms API
- Web Workers API
- Web Storage API
- Offline Web Applications
虽然介绍了不少新技术,但真正可以实际使用的却非常少。现在在中国主流的浏览器还是IE系列的,里面真正支持HTML5的只有IE 9,但是现在的IE 9还只是个测试版。IE 6连css 2都支持不全,更别谈HTML5了。更杯具的是HTML5的标准还没有最终确定下来,也就是说HTML5也不标准,它以后可能还会再变。
但我觉得HTML5可能会在中国很早地得到大规模地支持,因为搜狗浏览器、QQ浏览器5、Maxthon 3,它们的高速模式使用了WebKit核心,就连360浏览器也打算要内嵌WebKit了,而目前来说WebKit对HTML5的支持是最好的。就算这些浏览器的用户不默认开启高速模式,但是他也拥有了支持HTML5的平台,对于HTML5的推广是件好的事。
没有最好的技术,只有最适合的技术。个人认为对于HTML5是要了解一些,但不要过分地追求新技术,毕竟现在HTML5还不规范,支持也少。最后引用岁月如歌的一段话:
关注是可以的。有时间(我觉得大部分人其实都没时间),去尝尝鲜也是有益的。但是对于大部分营养不良的前端,推荐还是脚踏实地老老实实的去学一门传统编程语言,去把数据结构/基础算法/设计模式/数据库等等基础知识点给搞瓷实了再说。这样,等 HTML9 出来的时候,对你而言,无非就是淘汰了一些旧 API, 增加了一些新 API 而已。
动态载入JavaScript以及它的load事件
动态载入JavaScript
动态载入JavaScript非常简单,代码演示如下:
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'test.js';
head.appendChild(script);
侦测JavaScript是否载入
我们常常用JavaScript来给其它元素添加load事件,但如果给一个script自身添加load事件还真不是一件容易的事。对于非IE的高级浏览器来说和一般元素添加事件方法是一样的,代码演示如下:
script.onload=function(){
// do something
};
但对于IE来说则要复杂一点,不能直使用onload,而要使用onreadystatechange事件,通过onreadystatechange事件来判断script元素的readyState属性是否等于complete或者loaded,从而来确认script元素是否已经载入。代码演示如下:
script.onreadystatechange=function(){
if(this.readyState == 'loaded' || this.readyState == 'complete'){
// do something
}
};
readyState具有以下几个状态值:
- 0 : uninitialized
- 1 : loading
- 2 : loaded
- 3 : interactive
- 4 : complete
CSS中文字体转编码
在制作网页的时候,为了兼容大部分浏览器,我们常常要求在CSS样式文档中不出现中文字体的,尤其是在{}中,因此通过参照下表将其对应转编,可以将中文名转成英文名。
注意unicode2是直接输出为文本的。
比如:微软雅黑,我们在CSS中的设置为:
.font01{
font-family:"Microsoft Yahei";
}
也可以是对应的unicode形式:
.font02{
font-family:"\5FAE\8F6F\96C5\9ED1";
}
但微软雅黑对应的unicode2即微软正黑体写在样式文档里是没有效果的,因为unicode2是以文本形式输出的,这个可以将对应的unicode2放到html文档中尝试一下,对应输出微软雅黑四个字。
| 中文名 | 英文名 | Unicode | Unicode 2 |
|---|---|---|---|
| Mac OS | |||
| 华文细黑 | STHeiti Light [STXihei] | \534E\6587\7EC6\9ED1 | 华文细黑 |
| 华文黑体 | STHeiti | \534E\6587\9ED1\4F53 | 华文黑体 |
| 华文楷体 | STKaiti | \534E\6587\6977\4F53 | 华文楷体 |
| 华文宋体 | STSong | \534E\6587\5B8B\4F53 | 华文宋体 |
| 华文仿宋 | STFangsong | \534E\6587\4EFF\5B8B | 华文仿宋 |
| 丽黑 Pro | LiHei Pro Medium | \4E3D\9ED1 Pro | 丽黑 Pro |
| 丽宋 Pro | LiSong Pro Light | \4E3D\5B8B Pro | 丽宋 Pro |
| 标楷体 | BiauKai | \6807\6977\4F53 | 标楷体 |
| 苹果丽中黑 | Apple LiGothic Medium | \82F9\679C\4E3D\4E2D\9ED1 | 苹果丽中黑 |
| 苹果丽细宋 | Apple LiSung Light | \82F9\679C\4E3D\7EC6\5B8B | 苹果丽细宋 |
| Windows | |||
| 新细明体 | PMingLiU | \65B0\7EC6\660E\4F53 | 新细明体 |
| 细明体 | MingLiU | \7EC6\660E\4F53 | 细明体 |
| 标楷体 | DFKai-SB | \6807\6977\4F53 | 标楷体 |
| 黑体 | SimHei | \9ED1\4F53 | 黑体 |
| 宋体 | SimSun | \5B8B\4F53 | 宋体 |
| 新宋体 | NSimSun | \65B0\5B8B\4F53 | 新宋体 |
| 仿宋 | FangSong | \4EFF\5B8B | 仿宋 |
| 楷体 | KaiTi | \6977\4F53 | 楷体 |
| 仿宋_GB2312 | FangSong_GB2312 | \4EFF\5B8B_GB2312 | 仿宋_GB2312 |
| 楷体_GB2312 | KaiTi_GB2312 | \6977\4F53_GB2312 | 楷体_GB2312 |
| 微软正黑体 | Microsoft JhengHei | \5FAE\x8F6F\6B63\9ED1\4F53 | 微软正黑体 |
| 微软雅黑 | Microsoft YaHei | \5FAE\8F6F\96C5\9ED1 | 微软雅黑 |
| Office | |||
| 隶书 | LiSu | \96B6\4E66 | 隶书 |
| 幼圆 | YouYuan | \5E7C\5706 | 幼圆 |
| 华文细黑 | STXihei | \534E\6587\7EC6\9ED1 | 华文细黑 |
| 华文楷体 | STKaiti | \534E\6587\6977\4F53 | 华文楷体 |
| 华文宋体 | STSong | \534E\6587\5B8B\4F53 | 华文宋体 |
| 华文中宋 | STZhongsong | \534E\6587\4E2D\5B8B | 华文中宋 |
| 华文仿宋 | STFangsong | \534E\6587\4EFF\5B8B | 华文仿宋 |
| 方正舒体 | FZShuTi | \65B9\6B63\8212\4F53 | 方正舒体 |
| 方正姚体 | FZYaoti | \65B9\6B63\59DA\4F53 | 方正姚体 |
| 华文彩云 | STCaiyun | \534E\6587\5F69\4E91 | 华文彩云 |
| 华文琥珀 | STHupo | \534E\6587\7425\73C0 | 华文琥珀 |
| 华文隶书 | STLiti | \534E\6587\96B6\4E66 | 华文隶书 |
| 华文行楷 | STXingkai | \534E\6587\884C\6977 | 华文行楷 |
| 华文新魏 | STXinwei | \534E\6587\65B0\9B4F | 华文新魏 |
attachEvent中this指针问题
在IE中使用attachEvent给一个元素绑定行为时,事件中的this指针会指向window对象,而不是元素本身,但使用addEventListener或者以elem.onclick = someFunc这种形式绑定的行为则不会出现这种问题。解决的问题也很简单,就是通过call或者apply把this指针引向元素自己,jQuery中也是这样做的。
var _ele = document.getElementById('myElement');
try{
_ele.addEventListener('click',clickFunc,false);
}catch(e){
try{
_ele.attachEvent('onclick',function(){clickFunc.call(_ele)});
}catch(e){};
}
这样函数clickFunc中的this指针就会指向被绑定行为的元素了。