Yearly Archive for 2010

淘宝商城轮播(幻灯片)效果的jQuery实现及反思

淘宝网的前端开发团队是业界最优秀的前端开发团队之一。淘宝网和淘宝商城的每一个页面都凝结了淘宝前端开发者的心血——他们关心用户操作和感受,力求给用户最好的体验。

KISSY是淘宝前端团队自主设计的一个Javascript 类库,其设计原则是“小巧灵活、简洁实用,使用起来让人感觉愉悦”。KISSY还封装了一些常用的组件,比如图片轮播等各种Switchable组件,被广泛的应用到了淘宝网和淘宝商城的各个角落,但今天的主角……呃……好像是它,也许不是它,这并不重要,先让我们来试试基于jQuery的仿淘宝网图片轮播效果的实现,并作一些浅显的反思。

博主曾写过一个简单的jQuery幻灯插件Xslider。那么能不能通过对Xslider的定制,制作出符合我们要求的轮播效果呢?答案是可以的。下面我们看代码以及Demo:
Code:


Demo:

可以看到,通过对博主的Xslider插件进行简单的定制,我们貌似就可以做出类似淘宝商城的各种轮播特效。
然而实际工作中,需求往往是变化多端的,我们还应该考虑在其他情况下插件的可重用性:比如图片轮播每次不是切换单一张图片,而是多张图片;比如轮播的形式不仅仅是图片,有可能是文字,甚至每张幻灯片的版面都截然不同;再比如怎么去构建一个本质上与轮播类似的tab(标签)页(可能还要实现内容的AJAX加载)——诸如此类的情况我们在插件设计的时候也应该尽量考虑到。
反观博主自己开发的Xslider插件,一旦有新需求,往往会比较依赖对css、HTML结构、甚至是插件代码的修改以适应新需求,代码可重用的程度仍然比较低,而且长期这么修修补补,代码也容易变臃肿。其根本原因就是没有去分析这些特定需求、场景,从而进行不同层次的抽象,真正达到组件化。
当然,这么做也有好处就是,只进行了一层抽象,结构清晰,比较容易理解。
说到这里,竟免不了要拿jQuery的插件与KISSY的组件进行一番比较。可博主没有用过KISSY,只看过少量的文档,进行这番比较难免断章取义,所以留给读者和自己将来再作对比,暂且打住……mark here
那么在前端代码中,我们应该怎样做才能确保插件(组件)的可重用和扩展性呢?下面一段摘自《行进中的前端类库:KISSY》,供大家参考。

KISSY的组件严格遵守适度灵活原则,在特定的场景下进行设计。任何抽象场景,都有不同的抽象层次。比如淘宝首页的图片轮播,至少有以下三种层次的抽象:

  1. 图片轮播是可轮播的多张图片
  2. 图片轮播是可切换的一组内容
  3. 图片轮播是对命令的响应

第一种抽象,会让我们做出像TBra里的SimpleSide类似的组件,功能很纯粹单一。大部分站点用jQuery等代码实现的图片轮播,也是基于这种简单明了的抽象。

第二种抽象,会让我们思考更多。比如图片轮播和标签页切换的关系,从这一层的抽象来讲,标签页和轮播图片本质上一样的,都是一组可切换的内容。在这一层抽象上,我们就可以实现Switchable(可切换)组件,有了Switchable,所有可以抽象为可切换内容的可视化组件,就都可以快速基于Switchable来实现,而不是全新写一个。在淘宝首页上,大部分可视化组件都是Switchable组件,非常便捷。

第三层抽象,很抽象,但抽象层次越高,落地越难。基本所有交互组件,都可以抽象成为对用户行为的响应。适度灵活原则,能避免我们掉入过度抽象的陷阱。

改进Smarty的缓存过期检测

Smarty仍然是被广泛采用的模板引擎,国产的开源网店程序Ecshop就是使用Smarty作模板引擎,它广泛采用了Smarty的静态缓存技术。

然而,Smarty检查缓存新旧居然是通过往缓存文件的开头写入经过一串经过序列化的数组(记录着缓存的过期时间等信息)——检查的时候把第一个“<”出现之前的字符串读入并unserialize(),从而获取原本数组中记录着的缓存过期时间,进而来判断是否更新缓存。

这么做有一个缺点,就是每次检查缓存是否过期的时候都要进行一次读取文件和unserialize()操作,势必影响了效率,我们不妨用以下方法来取代Smarty默认的缓存机制:

$compile_file = '../temp/compile/index.html';
if (file_exist($compile_file))
{
    $filestat = stat($compile_file)
    if (time() - $tmp['mtime'] < $smarty->cache_lifetime) //如果缓存未过期则直接输出
    {
        echo file_get_contents($compile_file);
        exit(1);
    }
    //如果缓存过期了 生成缓存+输出
    do_some_db_query(); //一些数据库查询操作
    $html = $smarty->fetch($compile_file,$smarty->cache_id);
    file_put_contents($compile_filel);
    echo $html;
}

此外,根据“在输出缓存之前,永不加载没用的东西”这条原则,Smarty类的引入和实例化应该放在过期检测之后,而不是放在init.php里,这样,如果缓存存在,就直接输出缓存并终止代码的运行,能最大化的提升应用的效率。

在网上找到了篇牛人写的关于此方法的测试和改进:
http://www.9enjoy.com/optimize-smarty-html-test/

[转]MySQL+HandlerSocket = MySQL的功能+NoSQL的性能

下文转自国内某PHP大牛的博客,原文链接:http://www.dualface.com/index.php/archives/1124

最近看到一篇博客,用8核服务器跑MySQL达到了每秒750,000次PK(主键)查询。原文网址:http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html(翻墙)。

文章首先分析了MySQL查询时的瓶颈(SQL分析、数据表的打开关闭等),然后介绍了HandlerSocket插件。HandlerSocket插件让MySQL达到了近两倍于memcached的查询性能,灰常的niubi!

                           approx qps     server CPU util
MySQL via SQL                105,000      %us 60%  %sy 28%
memcached                    420,000      %us  8%  %sy 88%
MySQL via HandlerSocket      750,000      %us 45%  %sy 53%

MySQL+HandlerSocket的架构如下图(来自原文):

mysql_handlersocket_thumb.png

从图中可以看到,HandlerSocket开了9998和9999端口,分别用于读写操作。对于基于主键的CRUD操作,客户端通过HandlerSocket进行,省略了SQL分析、数据表的打开关闭等操作。而其他查询仍然通过MySQL的3306端口进行。

相比常见的memcached+MySQL的架构,MySQL+HandlerSocket架构有两个最明显的优势:

  • 节约内存:由于MySQL InnoDB本身就会缓存数据,所以没必要在memcached多保存一份。
  • 避免数据不一致性:引入memcached后,一个很头痛的问题就是保证数据的一致性。而去掉memcached后,由于所有的数据库操作都是直接达到InnoDB引擎,所以完全消除了此问题。

相对于其他NoSQL解决方案,MySQL+HandlerSocket也有优势:

  • 降低应用开发难度:由于SQL提供了丰富的查询功能,相当于大多数NoSQL来说,开发应用时更简单。
  • 降低风险:NoSQL各有特色,选择不慎会造成深远的影响。而且能够完全掌握NoSQL的技术人员也不够普遍,出了问题不一定能够马上解决。

不过,HandlerSocket虽然省掉了一些步骤,但要是内存不足以缓存大部分常用数据。那么HandlerSocket带来的优势就荡然无存了。因此在使用HandlerSocket时,服务器一定要具备足够的内存空间用于InnoDB的Buffer Pool。此外对PHP开发者来说,HandlerSocket目前还没有可用的PHP扩展。

作者说他们已经将HandlerSocket用于了生产环境,取得了很好的效果。作者目前就职于日本最大的社会化游戏平台提供商DeNA

最后,附上HandelrSocket的仓库地址,这是一个开源项目:http://github.com/ahiguti/HandlerSocket-Plugin-for-MySQL

发布一个jQuery插件-Xslider – 令我着迷的jQuery(二)

算是自己写的第一个jQuery插件,js代码很早就写好了,但是因为一个css问题被困住了,直到今天才重新想起。

Xslider:基于jQuery的拉样片特效插件,也可以用作jQuery Tab选项卡,目前支持四种切换特效:X轴、Y轴、渐变和基本,这里是Demo
使用方法很简单:

$("#slider1").Xslider();

自定义选项:

$("#slider1").Xslider({
    affect: 'scrollx', //效果  有scrollx|scrolly|fade|none
    speed: 800, //动画速度
    space: 5000, //时间间隔
    auto: true, //自动滚动
    trigger: 'mouseover', //触发事件 注意用mouseover代替hover
    conbox: '.conbox', //内容容器id或class
    ctag: 'a', //内容标签 默认为a
    switcher: '.switcher', //切换触发器id或class
    stag: 'a', //切换器标签 默认为a
    current:'cur', //当前切换器样式名称
    prebtn: '.pre', //TODO 前一张按钮
    nextbtn:'.next', //TODO 下一张按钮
    recycle:true, //TODO 是否循环
    rand:false //TODO 是否随机指定首张幻灯图片
});

最后说一句,IE6很邪恶,但我爱它的盒子模型。

我常用的gVim配置和插件

这几天一直在Linux底下折腾,免不了怀着一颗装B的心,把gVim打造成一个“接近IDE的编辑器”,再怀着一颗媚俗的心,来这里写一篇《我常用的gVim配置和配置》。但本人确确实实是体会到了gVim的高效,尤其是在使用笔记本键盘的情况下,号称“让你的双手不离开打字区”,这真是个伟大的设计思路。

先上一张我的gVim截图:

怎么样,还行吧,自我感觉挺酷的:-)

下面是我的gVim配置,都写了注释的:

"gVim启动窗口位置 大小
winpos 173 162
set lines=25 columns=108 

"设定文件编码
set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936

syntax on

"配色风格
colorscheme desert

"文本缩进设置
set tabstop=4
set softtabstop=4
set shiftwidth=4
set autoindent
set cindent
set cinoptions={0,1s,t0,n-2,p2s,(03s,=.5s,>1s,=1s,:1s
set nu

"如果没有下面这段就拷贝进来吧 虽然不知道干什么的
if &term=="xterm"
set t_Co=8
set t_Sb=^[[4%dm
set t_Sf=^[[3%dm
endif

"设定折叠方式
"set foldmethod=indent

"以下字符将被视为单词的一部分 (ASCII):
"set iskeyword+=33-47,58-64,91-96,123-128

"打开文件自动跳转到上次编辑的行
au BufReadPost * if line("'\"") > 0|if line("'\"") <= line("$")|exe("norm '\"")|else|exe "norm $"|endif|endif

"Get out of VI's compatible mode..
set nocompatible

"Sets how many lines of history VIM har to remember
set history=400

"文件在外部被修改则自动保存
set autoread

" vim用户界面

"Turn on WiLd menu
set wildmenu

"Always show current position
set ruler

"The commandbar is 2 high
set cmdheight=2

"Show line number 显示行号
set nu

"Set backspace
set backspace=eol,start,indent

"Bbackspace and cursor keys wrap to
set whichwrap+=<,>,h,l

"show matching bracets
set showmatch

"How many tenths of a second to blink
set mat=2

filetype plugin on

"同样适用于jQuery的js语法高亮
au BufRead,BufNewFile *.js set syntax=jquery

map  :NERDTreeToggle

nmap   :TlistToggle
let Tlist_Use_Right_Window=1
set tags=tags;/

"对NERD_commenter的设置
let NERDShutUp=1
"支持单行和多行的选择,//格式
map  ,c

" phpDocumentor for VIM
inoremap  :call PhpDocSingle()
nnoremap  :call PhpDocSingle()
vnoremap  :call PhpDocRange()

"对.vimrc配置文件的修改立即生效
autocmd! bufwritepost _vimrc source %

然后是我使用的插件:
NERDTreeToggle :用于导航和打开文件,在上面截图的左边区域
TlistToggle :用于导航代码中的类、变量以及函数(方法)
OmniComplete :代码的自动补全,快捷键是Ctrl+x Ctrl+o,支持很多种语言
NERDCommenter :用于给代码加注释
phpDocumentor :用于给php类和函数加文档 按下alt+/时

非常Cool的滑块导航菜单-令我着迷的jQuery(一)

As is known to us,jQuery是一个短小精悍的javascript library。它以”Write less,do more”的宗旨,以及提供许多成熟的插件及实现,俘获了无数爱偷懒的Programmers的心。今天和大家分享我在项目中使用jQuery编写的一处页面特效,我姑且自顾自的把它称作滑块导航菜单,是一种类似LavaLamp的特效,菜单按钮的背景会有鼠标跟随、以及弹簧动画的特效,很有意思(ps:大家如果有更好的命名方式,荒淫指出,哈哈)。
全部源代码如下,此外Demo地址,荒淫指教:
javascript(除了jQuery,还使用了easing扩展):

$(function(){
	$('#nav_btn_bg').fadeIn(0.2);
	$('#nav_btn').mouseover(function(e){ //这里用到了比事件绑定更高级的事件委托机制
		if(e.target.id=='home') {
			var ml = -5;
		}else if(e.target.id=='sk') {
			var ml = 145;
		}else if(e.target.id=='lottery') {
			var ml = 290;
		}
		$('#nav_btn_bg').stop(true).animate({marginLeft:ml},{easing: 'easeOutBack'});
	});
	$('#nav_btn').mouseleave(function(){
		$('#nav_btn_bg').stop(true).animate({marginLeft:[290,'easeOutBounce'],duration: 800}); //jQuery1.4以后才能这么写
	});
});

HTML(How To Make Love):

CSS样式:

@charset "utf-8";
/* CSS Document */
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,
form,fieldset,input,textarea,p,blockquote,th,td {
padding: 0;
margin: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
fieldset,img {
border: 0;
}
address,caption,cite,code,dfn,em,strong,th,var {
font-weight: normal;
font-style: normal;
}
ol,ul {
list-style: none;
}
caption,th {
text-align: left;
}
h1,h2,h3,h4,h5,h6 {
font-weight: normal;
font-size: 100%;
}
q:before,q:after {
content:”;
}
abbr,acronym { border: 0;
}
#header{
	width:100%;
	height:175px;
	background:url('head_bg.jpg') repeat-x;
}
#nav{
	width:960px;
	margin:0 auto;
	position:relative !important;
}
#logo{
	display:inline-block;
	width:325px;
	height:70px;
	margin-top:15px;
	float:left;
}
#nav_btn{
	height:60px;
	width:420px;
	float:left;
	margin-top:35px;
	margin-left:45px;
	background:url('nav_btn_bg_06.gif') no-repeat;
	position:relative;
}
#nav_bar{
	position:absolute;
	z-index:2;
}
#nav_btn a{
	display:inline-block;
	width:133px;
	height:55px;
}
#nav_btn_bg{
	width:120px;
	height:55px;
	background:#cccccc;
	-webkit-border-radius:5px;
	-moz-border-radius:5px;
	border-radius:5px;
	position:absolute;
	z-index:1;
	left:0px;
	top:2px;
	opacity:0.2;
	filter:alpha(opacity=20);
	margin-left:290px;
	display:none;
}

如何将删除的Ubuntu面板找回来

刚才因为淘气,把Ubuntu的上下面板都给删除鸟~

在网上搜索到了恢复面板到默认状态的方法如下

打开终端,终端窗口打开之后,立即在提示符后面输入下列命令:
gconftool –recursive-unset /apps/panel
(注意:每个斜杠 “/” 后面没有空格)
接下来输入下列命令:
rm -rf ~/.gconf/apps/panel

最后 重启Gnome,方法是:

Ctrl+Alt+F1登录到终端后

/etc/init.d/gdm restart

不要迷信IETester

今天由于部门唯一的美工Yang请假回家,下面这个页面的头部的切图任务就理所当然的就由我临时客串美工来完成。在做到导航按钮的时候,需要在鼠标移过的时候,背景会出现切换的效果。本来只要在a标签的:hover伪类中把背景图片换成另一张,而我觉得这样的切换太普通,没有什么挑战性。于是我决定试试自己实现类似LavaLamp的效果。

我在按钮下面加了个div作为背景,颜色是#cccccc,并设置透明度是20%。于是在chrome、Firefox和ie7+下,均能正常显示(ie8以下版本浏览器不能显示出圆角),而使用IETester模拟的IE6的下,却出现了不透明度的bug。尝试很多了方法,包括使用jQuery兼容的.css({‘opacity’:0.2})和ie6下的filter:alpha(opacity=20),均是一样的ugly。。如下图:

最后尝试使用原版IE6打开,发现一切正常,哇哈哈。。如果没亲自遇到,实在不敢相信,原先我是迷信ietester的,现在看来只有春哥和曾哥,才值得你信赖。

在JS控制台中使用jQuery

在有些时候,比如你正在浏览我的博客http://x1989.com,并且你想通过浏览器的js console控制台对页面进行调试,而你又不愿放弃熟悉的jQuery语法而使用原生的javascript,这时候只要地址栏中输入以下代码:

javascript:void((function(){var e=document.createElement('script');e.setAttribute('src','http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js');document.body.appendChild(e);})())

以下是在各种浏览器中调出javascript console的快捷键:

IE : F12

Chrome & Opera:Ctrl+Shift+i

FireFox : F12 (必须预装Firebug)

由此,你想到了什么……

Android Layout中使用include标签实现UI布局重用

1、创建一个独立的布局文件作为共享布局,common_layout.xml



  

2、在主布局中使用标签进行包含