其实,封装jquery插件很简单。
先看看,封装模板是什么?看下这个light-weight模式:
第一步 ,先写出简单demo,这里不写了,直接找一个吧。这里以一个tab选项卡为例
http://www.cnblogs.com/web-xiaobai/archive/2012/09/17/2689067.html
运行效果如下:
假设是自己写的,先看看核心逻辑是什么?
很简单,不做过多说明了。
第二步 ,改写代码为封装插件做准备,原文中的是index为顺序的,我想不要这种顺序,改用data属性来指明那个tab对应那个div。
先给内容区域,总体用div包装一下,同样要改变样式。
tab页和内容区域做关联,改用data属性关联。
第三步 ,用模板来封装插件,套用就行了,我做一个可以支持默认激活某一项的配置。
使用方式:
第四步 ,代码优化,每个li都有click,太浪费了。改用委托(原先用的delegate,经网友提醒,包括bind,我全改成on了)。
完整案例
如你所料,封装插件过程很简单,难的还是业务逻辑。
一般插件还要支持传入字符串当方法调用的,这里面没写,以后可能会补充进去。
比如有方法支持让第几个激活。还有,还要支持AMD的,这里只是一个简单例子,没有写进去。
本文完。
先看看,封装模板是什么?看下这个light-weight模式:
-
11121314151617181920212223242526272829303132333435363738394041propertyName : "value"}//插件类function Plugin ( element , options ) {//拿到dom元素,获得对应jq对象,要$(element)this . element = element ;//覆盖默认配置项this . options = $ . extend ({ } , defaults , options ) ;//缓存配置项this . _defaults = defaults ;//缓存插件名字(并没神马用)this . _name = pluginName ;//调用初始函数this . init ( ) ;}Plugin . prototype . init = function ( ) {//做你想做的事情}//fn就是prototype$ . fn [ pluginName ] = function ( options ) {//each表示对多个元素调用,用return 是为了返回this,进行链式调用return this . each ( function ( ) {//判断有没有插件名字 如果你不愿意加if 直接new就好了if ( !$ . data ( this , 'plugin_' + pluginName )) {//生成插件类实例。$ . data ( this , 'plugin_' + pluginName , new Plugin ( this , options )) ;}}) ;}}) ( jQuery , window , document ) ; //注意没有传第四个参数。
第一步 ,先写出简单demo,这里不写了,直接找一个吧。这里以一个tab选项卡为例
http://www.cnblogs.com/web-xiaobai/archive/2012/09/17/2689067.html
运行效果如下:
-
6789101112131415161718192021222324252627282930313233343536< script type = "text/javascript" >//http://www.cnblogs.com/web-xiaobai/archive/2012/09/17/2689067.html$ ( function ( ) {$ ( document ) . ready ( function ( ) {$ ( ".tab li" ) . click ( function ( ) {$ ( ".tab li" ) . eq ( $ ( this ) . index ( )) . addClass ( "cur" ) . siblings ( ) . removeClass ( 'cur' ) ;$ ( "div" ) . hide ( ) . eq ( $ ( this ) . index ( )) . show ( ) ;//另一种方法: $("div").eq($(".tab li").index(this)).addClass("on").siblings().removeClass('on');}) ;}) ;}) ;</ script >< style >div { margin: 0; padding: 0; width: 184 px; height: 200 px; border: 1 px solid #ccc; display: none; }.tab { margin: 0; padding: 0; list-style: none; width: 200 px; overflow: hidden; }.tab li { float: left; width: 60 px; height: 30 px; background: #ccc; color: #fff; border: 1 px solid red; text-align: center; line-height: 30 px; cursor: pointer; }.on { display: block; }.tab li .cur { background: blue; }</ style ></ head >< body >< ul class = "tab" >< li > 最新 </ li >< li class = "cur" > 热门 </ li >< li > 新闻 </ li ></ ul >< div > 11 </ div >< div class = "on" > 22 </ div >< div > 33 </ div ></ body ></ html >
假设是自己写的,先看看核心逻辑是什么?
-
1234567$ ( document ) . ready ( function ( ) {$ ( ".tab li" ) . click ( function ( ) {$ ( ".tab li" ) . eq ( $ ( this ) . index ( )) . addClass ( "cur" ) . siblings ( ) . removeClass ( 'cur' ) ;$ ( "div" ) . hide ( ) . eq ( $ ( this ) . index ( )) . show ( ) ;//另一种方法: $("div").eq($(".tab li").index(this)).addClass("on").siblings().removeClass('on');}) ;}) ;
很简单,不做过多说明了。
第二步 ,改写代码为封装插件做准备,原文中的是index为顺序的,我想不要这种顺序,改用data属性来指明那个tab对应那个div。
先给内容区域,总体用div包装一下,同样要改变样式。
tab页和内容区域做关联,改用data属性关联。
-
123456789$ ( document ) . ready ( function ( ) {$ ( ".tab li" ) . click ( function ( ) {var $this = $ ( this ) ;var c = $this . data ( "tab" ) ;alert ( c )$this . addClass ( "cur" ) . siblings ( ) . removeClass ( 'cur' ) ;$ ( ".tabContent" ) . find ( '>[data-tab=' + c + ']' ) . addClass ( "on" ) . siblings ( ) . removeClass ( 'on' ) ;}) ;}) ;
-
78910111213141516171819202122232425262728293031323334353637$ ( document ) . ready ( function ( ) {$ ( ".tab li" ) . click ( function ( ) {var $this = $ ( this ) ;var c = $this . data ( "tab" ) ;$this . addClass ( "cur" ) . siblings ( ) . removeClass ( 'cur' ) ;$ ( ".tabContent" ) . find ( '>[data-tab=' + c + ']' ) . addClass ( "on" ) . siblings ( ) . removeClass ( 'on' ) ;}) ;}) ;</ script >< style >.tabContent div { margin: 0; padding: 0; width: 184 px; height: 200 px; border: 1 px solid #ccc; display: none; }.tab { margin: 0; padding: 0; list-style: none; width: 200 px; overflow: hidden; }.tab li { float: left; width: 60 px; height: 30 px; background: #ccc; color: #fff; border: 1 px solid red; text-align: center; line-height: 30 px; cursor: pointer; }.tab li .cur { background: blue; }div .on { display: block; }</ style ></ head >< body >< ul id = "tab" class = "tab" >< li data-tab = "tab1" > 最新 </ li >< li data-tab = "tab2" class = "cur" > 热门 </ li >< li data-tab = "tab3" > 新闻 </ li ></ ul >< div id = "tabContent" class = "tabContent" >< div data-tab = "tab1" > 11 </ div >< div data-tab = "tab2" class = "on" > 22 </ div >< div data-tab = "tab3" > 33 </ div ></ div ></ body ></ html >
第三步 ,用模板来封装插件,套用就行了,我做一个可以支持默认激活某一项的配置。
-
891011121314151617181920212223242526272829303132333435363738this . element = element ;this . options = $ . extend ({ } , defaults , options ) ;this . _defaults = defaults ;this . _name = pluginName ;this . init ( ) ;}Plugin . prototype . init = function ( ) {var self = this ;$ ( this . element ) . find ( 'li' ) . click ( function ( ) {var $this = $ ( this ) ;var name = $this . data ( "tab" ) ;$this . addClass ( "cur" ) . siblings ( ) . removeClass ( 'cur' ) ;$ ( self . options . contentWrapper ) . find ( '>[data-tab=' + name + ']' ) . addClass ( "on" ) . siblings ( ) . removeClass ( 'on' ) ;}) ;var activeName = this . options . activeTabName ;alert ( activeName ) ;if ( activeName == null ) {$ ( this . element ) . find ( 'li' ) . eq ( 0 ) . click ( ) ;} else {$ ( this . element ) . find ( '>[data-tab=' + activeName + ']' ) . click ( ) ;}}$ . fn [ pluginName ] = function ( options ) {return this . each ( function ( ) {if ( !$ . data ( this , 'plugin_' + pluginName )) {$ . data ( this , 'plugin_' + pluginName , new Plugin ( this , options )) ;}}) ;}}) ( jQuery , window , document ) ;
使用方式:
-
1$ ( '#tab' ) . myTab ({ contentWrapper : '#tabContent' , activeTabName : 'tab2' }) ;
第四步 ,代码优化,每个li都有click,太浪费了。改用委托(原先用的delegate,经网友提醒,包括bind,我全改成on了)。
-
15161718192021222324252627282930313233343536373839404142434445var self = this ;var $element = $ ( this . element ) ;$element . on ( 'click' , 'li' , function ( ) {var $this = $ ( this ) ;var c = $this . data ( "tab" ) ;$element . trigger ( 'tab/change' , c ) ;}) ;$element . on ( 'tab/change' , function ( e , tabName ) {$element . find ( 'li' ) . removeClass ( 'cur' ) ;$element . find ( '>[data-tab=' + tabName + ']' ) . addClass ( "cur" ) ;}) ;var $contentWrapper = $ ( this . options . contentWrapper ) ;$element . on ( 'tab/change' , function ( e , tabName ) {$contentWrapper . find ( '>[data-tab]' ) . removeClass ( 'on' ) ;$contentWrapper . find ( '>[data-tab=' + tabName + ']' ) . addClass ( "on" ) ;}) ;var activeName = this . options . activeTabName ;if ( activeName == null ) {$element . find ( 'li' ) . eq ( 0 ) . click ( ) ;} else {$element . trigger ( 'tab/change' , this . options . activeTabName ) ;}}$ . fn [ pluginName ] = function ( options ) {return this . each ( function ( ) {if ( !$ . data ( this , 'plugin_' + pluginName )) {$ . data ( this , 'plugin_' + pluginName , new Plugin ( this , options )) ;}}) ;}}) ( jQuery , window , document ) ;
完整案例
-
48495051525354555657585960616263646566676869707172737475767778}}) ;}}) ( jQuery , window , document ) ;</ script >< script type = "text/javascript" >$ ( function ( ) {$ ( '#tab' ) . myTab ({ contentWrapper : '#tabContent' , activeTabName : 'tab2' }) ;})</ script >< style >.tabContent div { margin: 0; padding: 0; width: 184 px; height: 200 px; border: 1 px solid #ccc; display: none; }.tab { margin: 0; padding: 0; list-style: none; width: 200 px; overflow: hidden; }.tab li { float: left; width: 60 px; height: 30 px; background: #ccc; color: #fff; border: 1 px solid red; text-align: center; line-height: 30 px; cursor: pointer; }.tab li .cur { background: blue; }div .on { display: block; }</ style ></ head >< body >< ul id = "tab" class = "tab" >< li data-tab = "tab1" > 最新 </ li >< li data-tab = "tab2" > 热门 </ li >< li data-tab = "tab3" > 新闻 </ li ></ ul >< div id = "tabContent" class = "tabContent" >< div data-tab = "tab1" > 11 </ div >< div data-tab = "tab2" > 22 </ div >< div data-tab = "tab3" > 33 </ div ></ div ></ body ></ html >
如你所料,封装插件过程很简单,难的还是业务逻辑。
一般插件还要支持传入字符串当方法调用的,这里面没写,以后可能会补充进去。
比如有方法支持让第几个激活。还有,还要支持AMD的,这里只是一个简单例子,没有写进去。
本文完。