博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[js插件开发教程]原生js仿jquery架构扩展开发选项卡插件
阅读量:6649 次
发布时间:2019-06-25

本文共 10662 字,大约阅读时间需要 35 分钟。

jquery插件一般是这么干的: $.fn.插件名称 = function(){}, 把插件的名称加在.fn上,在源码里面实际上是扩展到构造函数的原型对象上,如果你没看过jquery的源代码,或者你曾经看过,但是不知道为什么把插件扩展到fn上,那么本篇文章就能解答你的疑惑。关于jquery插件开发方式,可以参考我的这篇文章:

关于选项卡这个功能具体怎么做,不在这里详解,这个是入门级的功能,本文重在讨论插件开发的架构,扩展,以及参数设置。

如果你使用过jquery的选项卡插件,或者其他类型的插件,他们一般都是这么调用的:

$( ".tab" ).tabs( {} )

$(".tab").tabs( function(){} );

一种是传递参数定制插件行为

一种是传递函数定制插件行为

$(".tab") 选择到元素,然后返回的是jquery对象

tabs方法扩展在fn上就是扩展都jquery构造函数的原型对象上, 那么对象( $(".tab") )调用原型对象上的方法( tabs )当然就顺利成章了。

所以jquery插件扩展本质就是: 构造函数 + 原型对象扩展方法

定义一个构造+原型的方式,下面代码的原理,我在这篇文章有详细论述:

1 var G = function( selectors, context ){ 2         return new G.fn.init( selectors, context ); 3     } 4     G.fn = G.prototype = { 5         length : 0, 6         constructor : G, 7         size : function(){ 8             return this.length; 9         },10         init : function( selector, context ){11             this.length = 0;12             context = context || document;13             if ( selector.indexOf( '#' ) == 0 ){14                 this[0] = document.getElementById( selector.substring( 1 ) );15                 this.length = 1;16             }else {17                 var aNode = context.querySelectorAll( selector );18                 for( var i = 0, len = aNode.length; i < len; i++ ) {19                     this[i] = aNode[i];20                 }21                 this.length = len;22             }23             this.selector = selector;24             this.context = context;25             return this;26         }27     }28 29     G.fn.init.prototype = G.fn;
View Code

接下来,我们还要添加一个插件扩展机制:

1 G.extend = G.fn.extend = function () { 2         var i = 1, 3             len = arguments.length, 4             dst = arguments[0], 5             j; 6         if (dst.length === undefined) { 7             dst.length = 0; 8         } 9         if (i == len) {10             dst = this;11             i--;12         }13         for (; i < len; i++) {14             for (j in arguments[i]) {15                 dst[j] = arguments[i][j];16                 dst.length++;17             }18         }19         return dst;20     };
View Code

在这篇文章: 有详细的论述,extend插件扩展机制

像使用jquery一样暴露接口:

var $ = function( selectors, context ){
return G( selectors, context ); } window.$ = $;

这个插件的扩展机制和元素选择机制就完成了,如果要扩展插件,只要在

G.fn上扩展插件的名称即可,如:

1 G.fn.tabs = function( options ){ 2     options = options || {}; 3     var defaults = { 4         contentClass : 'tab-content', 5         navClass : 'tab-nav', 6         activeClass : 'active', 7         triggerElements : '*', 8         activeIndex : 0, 9         evType : 'click',10         effect : 'none'11     };12 13     var opt = G.extend( {}, defaults, options );14     return this;15 }

这样,我们就在G的原型对象上扩展了一个tabs( 选项卡 )插件

options可以定制插件的行为:

contentClass : 'tab-content',     选项卡内容区域的class名称 navClass : 'tab-nav',             标签卡区域的class名称 activeClass : 'active',           标签卡默认选择的class名称:active triggerElements : '*',            标签卡默认触发元素 activeIndex : 0,                  默认选中第几个标签卡 evType : 'click',                 选项卡触发的事件类型 effect : 'none'                   是否有过渡特效:如透明度 var opt = G.extend( {}, defaults, options );

这一段是把定制的配置和默认配置合成到一个对象opt里面,后面的插件行为,就可以根据opt的配置进行定制,这是插件开发参数定制中,常用的一招。

这样做的好处,可以防止污染默认配置defaults

1  var tabContent = this[0].querySelector( "." + opt.contentClass );2         var tabContentEle = tabContent.children;3         var tabNavEle = this[0].querySelectorAll( "." + opt.navClass + '>' + opt.triggerElements );4 5         var _contentLen = tabContentEle.length;6         var _index = opt.activeIndex;

获取对应的元素。

有了选项卡的元素和配置,我们就开始做业务处理(为所有选项卡添加处理的事件,进行选项卡切换)

定义一个专门的对象_api = {}, 扩展业务api

1 G.fn.tabs = function( options ){ 2         options = options || {}; 3         var defaults = { 4             contentClass : 'tab-content', 5             navClass : 'tab-nav', 6             activeClass : 'active', 7             triggerElements : '*', 8             activeIndex : 0, 9             evType : 'click',10             effect : 'none'11         };12 13         var opt = G.extend( {}, defaults, options );14 15         var tabContent = this[0].querySelector( "." + opt.contentClass );16         var tabContentEle = tabContent.children;17         var tabNavEle = this[0].querySelectorAll( "." + opt.navClass + '>' + opt.triggerElements );18 19         var _contentLen = tabContentEle.length;20         var _index = opt.activeIndex;21 22         var _api = {};23 24         _api.setIndex = function( index ){25             //当前标签加上active样式,其余标签删除active样式26             for ( var i = 0; i < _contentLen; i++ ) {27                 if ( tabNavEle[i].classList.contains( 'active' ) ) {28                     tabNavEle[i].classList.remove('active');29                 }30             }31             tabNavEle[index].classList.add( 'active' );32             switch ( opt.effect ){33                 case 'fade':34                     break;35                 default:36                     for ( var i = 0; i < _contentLen; i++ ) {37                         tabContentEle[i].style.display = 'none';38                     }39                     tabContentEle[index].style.display = 'block';40                     _index = index;41             }42         }43 44         _api.setIndex( _index ); //默认的选项卡45 46         //所有的标签绑定事件47         for( var i = 0, len = tabNavEle.length; i < len; i++ ) {48             tabNavEle[i].index = i;49             tabNavEle[i].addEventListener( opt.evType, function(){50                 var i = this.index;51                 _api.setIndex( i );52             }, false );53         }54 55         return this;56     }
View Code

完整的插件代码:

1 /**  2  * Created by ghostwu(吴华).  3  */  4 (function(){  5     var G = function( selectors, context ){  6         return new G.fn.init( selectors, context );  7     }  8     G.fn = G.prototype = {  9         length : 0, 10         constructor : G, 11         size : function(){ 12             return this.length; 13         }, 14         init : function( selector, context ){ 15             this.length = 0; 16             context = context || document; 17             if ( selector.indexOf( '#' ) == 0 ){ 18                 this[0] = document.getElementById( selector.substring( 1 ) ); 19                 this.length = 1; 20             }else { 21                 var aNode = context.querySelectorAll( selector ); 22                 for( var i = 0, len = aNode.length; i < len; i++ ) { 23                     this[i] = aNode[i]; 24                 } 25                 this.length = len; 26             } 27             this.selector = selector; 28             this.context = context; 29             return this; 30         } 31     } 32  33     G.fn.init.prototype = G.fn; 34     G.extend = G.fn.extend = function () { 35         var i = 1, 36             len = arguments.length, 37             dst = arguments[0], 38             j; 39         if (dst.length === undefined) { 40             dst.length = 0; 41         } 42         if (i == len) { 43             dst = this; 44             i--; 45         } 46         for (; i < len; i++) { 47             for (j in arguments[i]) { 48                 dst[j] = arguments[i][j]; 49                 dst.length++; 50             } 51         } 52         return dst; 53     }; 54  55     G.fn.tabs = function( options ){ 56         options = options || {}; 57         var defaults = { 58             contentClass : 'tab-content', 59             navClass : 'tab-nav', 60             activeClass : 'active', 61             triggerElements : '*', 62             activeIndex : 0, 63             evType : 'click', 64             effect : 'none' 65         }; 66  67         var opt = G.extend( {}, defaults, options ); 68  69         var tabContent = this[0].querySelector( "." + opt.contentClass ); 70         var tabContentEle = tabContent.children; 71         var tabNavEle = this[0].querySelectorAll( "." + opt.navClass + '>' + opt.triggerElements ); 72  73         var _contentLen = tabContentEle.length; 74         var _index = opt.activeIndex; 75  76         var _api = {}; 77  78         _api.setIndex = function( index ){ 79             //当前标签加上active样式,其余标签删除active样式 80             for ( var i = 0; i < _contentLen; i++ ) { 81                 if ( tabNavEle[i].classList.contains( 'active' ) ) { 82                     tabNavEle[i].classList.remove('active'); 83                 } 84             } 85             tabNavEle[index].classList.add( 'active' ); 86             switch ( opt.effect ){ 87                 case 'fade': 88                     break; 89                 default: 90                     for ( var i = 0; i < _contentLen; i++ ) { 91                         tabContentEle[i].style.display = 'none'; 92                     } 93                     tabContentEle[index].style.display = 'block'; 94                     _index = index; 95             } 96         } 97  98         _api.setIndex( _index ); //默认的选项卡 99 100         //所有的标签绑定事件101         for( var i = 0, len = tabNavEle.length; i < len; i++ ) {102             tabNavEle[i].index = i;103             tabNavEle[i].addEventListener( opt.evType, function(){104                 var i = this.index;105                 _api.setIndex( i );106             }, false );107         }108 109         return this;110     }111 112     var $ = function( selectors, context ){113         return G( selectors, context );114     }115     window.$ = $;116 })();
View Code

选项卡布局:

1  2  3  4     
5
6 选项卡插件 - by ghostwu 7
8 9 16 17 18
19
20
26
27

内容1

28

内容2

29

内容3

30

内容4

31
32
33
34 35
View Code

选项卡插件样式:

1 * { 2     margin: 0; 3     padding: 0; 4 } 5 body { 6     font-size: 14px; 7     font-family: Tahoma, Verdana,"Microsoft Yahei"; 8 } 9 a{10     text-decoration: none;11     color:#000;12 }13 ul,li{14     list-style-type: none;15 }16 img {17     border:none;18 }19 .main {20     width:960px;21     margin:20px auto;22 }23 .tab{24     margin: 0 auto 20px;25 }26 .tab1 .tab-nav{27     margin-bottom:8px;28 }29 .tab .tab-nav {30     overflow:hidden;31 }32 .tab1 .tab-nav .active{33     border-bottom:1px solid #000;34 }35 .tab1 .tab-nav li {36     float:left;37     margin:0 10px;38 }39 .tab1 .tab-nav li a {40     line-height:40px;41     display:block;42 }43 .tab1 .tab-content {44     height:250px;45     overflow:hidden;46 }47 .tab1 .tab-content p {48     height:250px;49     background:#eee;50 }
View Code

最终效果:

 

转载地址:http://gluto.baihongyu.com/

你可能感兴趣的文章
Centos7通过Docker安装Sentry(哨兵)
查看>>
加入收藏兼容ie和火狐
查看>>
Linux常用的网络命令
查看>>
树莓派蓝牙连接
查看>>
Android 网络编程
查看>>
设计师的视觉设计五项修炼
查看>>
转:: 刺鸟:用python来开发webgame服务端(4)
查看>>
十款被人忽视的堪称神器的软件【纯干货】
查看>>
ZOJ 3596Digit Number(BFS+DP)
查看>>
检测Java程序运行时间的2种方法(高精度的时间[纳秒]与低精度的时间[毫秒])...
查看>>
JAVA基础知识|集合
查看>>
poj 2752 - Seek the Name, Seek the Fame
查看>>
exforce_download() -- 对CI中force_download()增强后的函数(不依赖CI)
查看>>
第七次课后作业
查看>>
Python中创建守护进程
查看>>
TOJ 2703: Cow Digit Game
查看>>
将字典转换成变量, 字符串与列表相互转换
查看>>
架构中的7个设计原则
查看>>
SDUT 3374 数据结构实验之查找二:平衡二叉树
查看>>
php的错误级别
查看>>