msgbartop
PHP Web开发技术
msgbarbottom

24 十一 11 jQuery性能优化要点

网上这方面的要点一大堆,总结了几点,稍懂的看下要点就知道大概,不细说,只为记录下:

  1. 总是从ID选择器开始继承
  2. 在class前使用tag
  3. 将jquery对象缓存起来,如果页面多出引用,可以适当的把变量存成全局变量
  4. 掌握强大的链式操作
  5. 使用子查询
  6. 对直接的DOM操作进行限制
  7. 冒泡
  8. 消除无效查询
  9. 推迟到 $(window).load
  10. 压缩js,在线压缩地址:http://dean.edwards.name/packer/
  11. 全面掌握jquery库
  12. 使用最新版本(这个看情况把,新版一般性能好,但同时体积也大)
  13. 用for替代each
  14. 给选择器指定前后文
  15. 避免使用concat(),利用join()处理长字串

第7点需要说明下:

7. 冒泡

除非在特殊情况下, 否则每一个js事件(例如:click, mouseover, 等.)都会冒泡到父级节点. 当我们需要给多个元素调用同个函数时这点会很有用.

代替这种效率很差的多元素事件监听的方法就是, 你只需向它们的父节点绑定一次, 并且可以计算出哪个节点触发了事件.

例如, 我们要为一个拥有很多输入框的表单绑定这样的行为: 当输入框被选中时为它添加一个class

像这样绑定事件是低效的:

  1. $("#entryform input").bind("focus", function(){
  2.     $(this).addClass("selected");
  3. }).bind("blur", function(){
  4.     $(this).removeClass("selected");
  5. });

我们需要在父级监听获取焦点和失去焦点的事件:

  1. $("#entryform").bind("focus", function(e){
  2.         // e.target grabs the node that triggered the event.
  3.     var cell = $(e.target);
  4.     cell.addClass("selected");
  5. }).bind("blur", function(e){
  6.     var cell = $(e.target);
  7.     cell.removeClass("selected");
  8. });

父级元素扮演了一个调度员的角色, 它可以基于目标元素绑定事件. 如果你发现你给很多元素绑定了同一个事件监听, 那么你肯定哪里做错了.

Tags: ,

04 十一 11 李开复:如何有效率地利用时间?

人的一生两个最大的财富是:你的才华和你的时间。才华越来越多,但是时间越来越少,我们的一生可以说是用时间来换取才华。如果一天天过去了,我们的时间少了,而才华没有增加,那就是虚度了时光。所以,我们必须节省时间,有效率地使用时间。
李开复 有效利用时间
如何有效率地利用时间呢?我有下面几个建议:

1、做你真正感兴趣、与自己人生目标一致的事情。

我发现我的“生产力”和我的“兴趣”有着直接的关系,而且这种关系还不是单纯的线性关系。如果面对我没有兴趣的事情,我可能会花掉40%的时间,但只能产生20%的效果;如果遇到我感兴趣的事情,我可能会花100%的时间而得到200%的效果。要在工作上奋发图强,身体健康固然重要,但是真正能改变你的状态的关键是心理而不是生理上的问题。真正地投入到你的工作中,你需要的是一种态度、一种渴望、一种意志。

2、知道你的时间是如何花掉的。

挑一个星期,每天记录下每30分钟做的事情,然后做一个分类(例如:读书、准备GRE、和朋友聊天、社团活动等)和统计,看看自己什么方面花了太多的时间。凡事想要进步,必须先理解现状。每天结束后,把一整天做的事记下来,每15分钟为一个单位(例如:1:00—1:15等车,1:15—1:45搭车,1:45—2:45与朋友喝茶……)。在一周结束后,分析一下,这周你的时间如何可以更有效率地安排?有没有活动占太大的比例?有没有方法可以增加效率?

3、使用时间碎片和“死时间”。

如果你做了上面的时间统计,你一定发现每天有很多时间流失掉了,例如等车、排队、走路、搭车等,可以用来背单字、打电话、温习功课等。现在随时随地都能上网,所以没有任何借口再发呆一次。我前一阵和同事一起出差,他们都很惊讶为什么我和他们整天在一起,但是我的电子邮件都可以及时回答?后来,他们发现,当他们在飞机上和汽车上聊天、读杂志和发呆的时候,我就把电子邮件全回了。重点是,无论自己忙还是不忙,你要把那些可以利用时间碎片做的事先准备好,到你有空闲的时候有计划地拿出来做。

4、要事为先 – 每天一大早挑出最重要的三件事,当天一定要能够做完。

在工作和生活中每天都有干不完的事,唯一能够做的就是分清轻重缓急。要理解急事不等于重要的事情。每天除了办又急又重要的事情外,一定要注意不要成为急事的奴隶。有些急但是不重要的事情,你要学会放掉,要能对人说 no! 而且每天这三件事里最好有一件重要但是不急的,这样才能确保你没有成为急事的奴隶。

5、要有纪律。

有的年轻人会说自己“没有时间学习”,其实,换个说法就是“学习没有被排上优先级次序”。曾经有一个教学生做时间管理的老师,他上课时带来两个大玻璃缸和一堆大小不一的石头。他做了一个实验,在其中一个玻璃缸中先把小石、砂倒进去,最后大石头就放不下了。而另一个玻璃缸中先放大石头,其它小石和砂却可以慢慢渗入。他以此为比喻说:“时间管理就是要找到自己的优先级,若颠倒顺序,一堆琐事占满了时间,重要的事情就没有空位了。”

6、运用80%—20%原则。

人如果利用最高效的时间,只要20%的投入就能产生80%的效率。相对来说,如果使用最低效的时间,80%的时间投入只能产生20%效率。一天头脑最清楚的时候,应该放在最需要专心的工作上。与朋友、家人在一起的时间,相对来说,不需要头脑那么清楚。所以,我们要把握一天中20%的最高效时间(有些人是早晨,也有些人是下午和晚上;除了时间之外,还要看你的心态,血糖的高低,休息是否足够等综合考量),专门用于最困难的科目和最需要思考的学习上。许多同学喜欢熬夜,但是晚睡会伤身,所以还是尽量早睡早起。

7、平衡工作和家庭。

我对于家庭的时间分配是用下列的原则:

划清界限、言出必行——对家人做出承诺后,而且一定要做到,但是希望其他时间得到谅解。制定较低的期望值以免造成失望。

忙中偷闲——不要一投入工作就忽视了家人,有时10分钟的体贴比10小时的陪伴还更受用。

闲中偷忙——学会怎么利用时间碎片。例如:家人没起床的时候,你就可以利用这段空闲时间去做你需要的工作。

注重有质量的时间(quality time)——时间不是每一分钟都是一样的,有时需要全神贯注,有时坐在旁边上网就可以了。要记得家人平时为你牺牲很多,度假、周末是你补偿的机会。

Tags: ,

24 九 11 chive安装注意事项

chive是一个类似phpmyadmin的管理mysql数据库的系统(当然基于B/S),开源并采用Yii框架编写(官网地址:http://www.chive-project.com/),所以建议学习Yii框架的TX可以下下来学习下。

chive的安装其实比phpmyadmin简单咯,直接放在web服务器的指定目录下访问即可,当然你得满足一些安装条件:比如php的PDO扩展、json扩展还有在chive目录下开启rewrite等,官方都有说明,详见:http://www.chive-project.com/Wiki/Installation

但是笔者安装后,用mysql的账户登录发现请求好久最终页面空白无任何响应,分析程序代码(当前版本为0.5.1)才知道,在SiteController.php中的actionIndex()方法中有访问网上的一个xml文件,即如下这行:

$xml = @simplexml_load_file('http://feeds.launchpad.net/chive/announcements.atom');

所以如果无网络情况下或者公司网络访问受限的情况下无法使用系统,解决就很简单咯,直接在有网络条件的情况下下载这个文件并放在指定目录下,如系统的根目录,那么将这行代码替换成下面即可:

$xml = @simplexml_load_file('announcements.atom');

Tags: , ,

14 九 11 (转)深入理解ob_flush和flush的区别

关于缓冲的引言(摘自:http://hi.baidu.com/wd_828/blog/item/6e3e71dcfe9a6bf676c638d6.html):

buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入 一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁 盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。

同样的道理,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示, 而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方echo/pring -> php buffer -> tcp buffer -> browser

比如我们用的apache作为web服务器,那么此处的tcp buffer就是我们的apache的buffer了,关于ob_flush和flush的区别, Laruence的博文(http://www.laruence.com/2010/04/15/1414.html)讲的比较详细:

ob_flush/flush在手册中的描述, 都是刷新输出缓冲区, 并且还需要配套使用, 所以会导致很多人迷惑…

其实, 他们俩的操作对象不同, 有些情况下, flush根本不做什么事情..

ob_*系列函数, 是操作PHP本身的输出缓冲区.

所以, ob_flush是刷新PHP自身的缓冲区.

而flush, 严格来讲, 这个只有在PHP做为apache的Module(handler或者filter)安装的时候, 才有实际作用. 它是刷新WebServer(可以认为特指apache)的缓冲区.

在apache module的sapi下, flush会通过调用sapi_module的flush成员函数指针, 间接的调用apache的api: ap_rflush刷新apache的输出缓冲区, 当然手册中也说了, 有一些apache的其他模块, 可能会改变这个动作的结果..

有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,
这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。
 
甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape
浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在
接受到  标记之前,不会显示出整个表格。
 
一些版本的 Microsoft Internet Explorer 只有当接受到的256个
字节以后才开始显示该页面,所以必须发送一些额外的空格来让这
些浏览器显示页面内容。

所以, 正确使用俩者的顺序是. 先ob_flush, 然后flush,

当然, 在其他sapi下, 不调用flush也可以, 只不过为了保证你代码的可移植性, 建议配套使用.

Tags: , ,

04 九 11 PHPExcel读取并处理excel单元格中的图片

先来看下基本需求:将excel中单元格中的内容包括图片导入到数据库中的指定字段的值,那么假如单元格中既有内容“123”,又贴了某个图片,那我们需要读出该单元格内容和把图片上传并构造成<img/>加入到字段值中,例如存入的字段值为:”123<img src=’images/test.jpg’ />”

首先说明下,经过我测试发现:在excel中贴图片,那么这个图片属于图片左上角开始坐标所在的单元格,即图片占有的其他单元格并不拥有该图片。

来看下基本的代码:

  1. require_once '../Classes/PHPExcel/IOFactory.php';
  2.  
  3. $objReader = PHPExcel_IOFactory::createReader('Excel5');
  4. // 设置载入含有贴图的 sheet
  5. $objReader->setLoadSheetsOnly(array('sheet1'));
  6. $objPHPExcel = $objReader->load('test.xls');
  7.  
  8. $drawing = new PHPExcel_Writer_Excel2007_Drawing();
  9.  
  10. $drawingHashTable = new PHPExcel_HashTable();
  11. $drawingHashTable->addFromSource($drawing->allDrawings($objPHPExcel));
  12.  
  13. for ($i = 0; $i < $drawingHashTable->count(); ++$i)
  14. {
  15.     $memoryDrawing = $drawingHashTable->getByIndex($i);
  16.     if ($memoryDrawing instanceof PHPExcel_Worksheet_MemoryDrawing)
  17.     {
  18.         $filename = 'images/' . $memoryDrawing->getCoordinates() . '_' . $memoryDrawing->getHashCode() . '.jpg';
  19.         // 将图片存到指定的目录
  20.         imagejpeg($memoryDrawing->getImageResource(), $filename);
  21.         // 获得该图片所在的单元格
  22.         $cell = $memoryDrawing->getWorksheet()->getCell($memoryDrawing->getCoordinates());
  23.         // 将该单元格的值设置为单元格的文本加上图片的 img 标签
  24.         $cell->setValue($cell->getValue() . '<img src="' . $filename . '" />');
  25.     }
  26. }
  27. // 再处理将这些单元格的值存入数据库
  28. // ... ...

上面的代码主要参考Writer类中的save()方法的一些原理,如果想把读出的图片继续存入到excel,那可以参考他的代码

Tags: , ,

04 九 11 PHPExcel读excel03和excel07的区别

PHPExcel是php操作excel的一个类库,详细可以去官网了解下:http://phpexcel.codeplex.com/

当你需要读excel时,你可以直接用工厂类PHPExcel_IOFactory的load方法载入,他会根据文件类型使用对应的的Reader对象读取并装载成一个PHPExcel对象,如下:

  1. // 载入 excel03
  2. $objPHPExcel = PHPExcel_IOFactory::load("test.xls");
  3. // 载入 excel07
  4. $objPHPExcel = PHPExcel_IOFactory::load("test.xlsx");

当然也可以显式的用PHPExcel_IOFactory的createReader后,在用Reader对象的load方法装载,这样的优点是可以更多的定义载入的选项,比如我们为了性能只载入excel的指定sheet,如下:

  1. // 创建 Reader 对象,参数为类型,Excel5 适用于 excel97-03, 如果 excel07 则为 Excel2007
  2. $objReader = PHPExcel_IOFactory::createReader("Excel5");
  3. // 注意参数是 sheet 的名字数组而不是 sheet 的索引
  4. $objReader->setLoadSheetsOnly(array('sheet1', 'sheet2'));
  5. // 这里的文件类型要符合上面创建的类型
  6. $objPHPExcel = $objReader->load("test.xls");

其他的具体用法参考他给的文档和示例吧,在此就不详述了。

下面回到标题说到的重点,我们通常读取单元格的值的时候使用下面方式获得

  1. $objPHPExcel->getSheet(1)->getCell('A1')->getValue();

但是对于存在的值为空单元格,excel07下上面返回的是空字符串,而excel03下则返回null,而对于不存在的单元格03和07统一返回null,所以你不能通过”$cellvalue===null”这种方式判断某单元格是否存在,本人就犯了这个错误调了好久才找到是这个原因,悲催。。。

通过看他的代码,才找到正确的判断单元格是否存在的方法,就是调用PHPExcel_Worksheet对象的cellExists方法判断,如下:

  1. $objPHPExcel->getSheet(1)->cellExists('A1');

另外,对于合并单元格,通常只有合并中的第一个单元格才有对应的值,其他的值都为空,但是通常我们的需求是对于合并的每个单元格都想是对应的值,这种需求实现起来也比较简单,我们可以遍历该sheet的所有单元格,看我们要读取的单元格是否属于其中,如果属于则取这个合并单元格的第一个格子的值就可以了,封装成函数大致的代码如下:

  1. $cell = $objPHPExcel->getSheet(1)->getCell('A5');
  2. $cellValue = $cell->getValue();
  3. if (!$cellValue)
  4. {
  5.     foreach ($objPHPExcel->getSheet(1)->getMergeCells() as $mergeCell)
  6.     {
  7.         if ($cell->isInRange($mergeCell))
  8.         {
  9.             list($startCell,$endCell) = explode(':', $mergeCell);
  10.             return $objPHPExcel->getSheet(1)->getCell($startCell)->getValue();
  11.         }
  12.     }
  13. }
  14. return $cellValue;

Tags: , ,

20 八 11 (转)让svn自动更新代码注释中的版本号

作者: 蓝色夏威夷
原文地址: http://www.coderbolg.com/content/140.html

最近在做代码规范方面的工作,以前使用Eclipse时有插件支持将SVN版本号自动更新到代码页头注释中去。现在用Zend Studio 7来开发PHP项目,得找一个替代方案来做这个。后来在SVN手册中找到了一个非常简单的解决方案:

1、打开C:/Users/[username]/AppData/Roaming/Subversion文件夹

2、找到 config文件,并打开

3、找到 nable-auto-props = yes 行,去掉行首的注释;

在[auto-props]节上添加以下字段:

*.css = svn:keywords=Id
*.php = svn:keywords=Id
*.html = svn:keywords=Id
*.tpl = svn:keywords=Id
*.txt = svn:keywords=Id
*.js = svn:keywords=Id

保存后创建一个文件,并在文件注释处添加 $Id$ ,然后添加并提交到版本库。提交成功再回过头看看这个文件,当$Id$被替换成类似这样:

$Id: UsersController.php 19629 2011-05-09 10:18:16Z zhuwanchun $

说明已经可以自动将SVN版本号更新到注释啊。注意,这种替换只对新创建的文件有效;当在已经提交到版本库中的文件添加$Id$发现并不会被替换成当前的版本号。

Tags: , ,

15 六 11 Step4:配置blog前台的url和添加前台页面(django项目djcms)(待续)

后台已经基本具备所需功能,虽然还有待完善,但是我们的注意力先转移到前台显示上,后台以后再完善!

1、前台显示博客的需求

前台的博客详细内容我们设计了两种方式的url访问,具体如下:
第一种:根据blog主键id来访问,如/blog/3.html,其中3为指定博客的id,id为整数
第二种:根据blog的别名字段alias来访问,如/blog/django_13-framework,其中django13-framework为指定博客的别名,别名应由字母、数字、下划线、短横线组成(设置别名的作用是可以在url中添加与文章相关的关键字,有利于seo)

2、初步实现方案

首先我们先配置url,由于我们要为每个app单独管理自己的url配置,所以我们可以在根目录下的urls.py中添加下面代码:
(全文 …)

Tags: , ,