88570299 2019-11-19
jquery插件的封装过程。
使用过很多的jquery的插件,但是不了解它们到底是怎样做的,今天就来封装一个最常见的tab插件,看看具体的封装过程。
tip:完整代码下载在最后面,需要的直接跳过去看
常见的tab支持自动切换,点击切换,动画切换,默认选择等等,根据这些功能先来把html结构搭建起来:
//index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tab选项卡封装插件</title> </head> <body> <div class="tab js-tab"> <ul class="tab_nav"> <li class="active"><a href="javascript:;">新闻</a></li> <li><a href="javascript:;">娱乐</a></li> <li><a href="javascript:;">电影</a></li> <li><a href="javascript:;">科技</a></li> </ul> <div class="content_wrap"> <div class="content_item current">a</div> <div class="content_item">b</div> <div class="content_item">c</div> <div class="content_item">d</div> </div> </div> </body> </html>
它是长这个样子,够丑,下一步来美化一下:
引入个tab.css样式,书写一下样式:
//tab.css *{margin: 0;padding: 0;} ul,li{list-style: none;} body{padding: 100px;background-color: #323232;font-size: 12px;font-family: "微软雅黑";} p{color:#6ec;font-weight: bold; background: #fff;height:20px;line-height: 20px;border-radius: 5px;padding:5px;} .tab_view{ float: left; margin-right: 50px; } .tab_view p{ color: #999; margin: 20px 0; } .tab{ width: 300px; } .tab_nav{ height: 30px; } .tab_nav li{ float: left; margin-right: 5px; background-color: #767676; border-radius: 3px 3px 0 0; } .tab_nav li a{ display: block; height: 30px; line-height: 30px; padding: 0 20px; color: #fff; text-decoration: none; } .tab_nav li.active{ background-color: #fff; } .tab_nav li.active a{ color: #767676; } .content_wrap{ height: 200px; padding: 5px; background-color: #fff; } .content_item{ font-size: 60px; text-align: center; line-height: 200px; width: 290px; height: 200px; display: none; position: absolute; } .content_wrap div.current{ display: block; } .content_item:first-child{ background-color: gray; } .content_item:nth-child(2){ background-color: lightblue; } .content_item:nth-child(3){ background-color: pink; } .content_item:nth-child(4){ background-color: lightgreen; }
它就长成这个样子了,看着舒服多了,马上进行下一步,插件封装:
在封装插件前,先来引入jquery和tab.js,在tab.js中进行具体的开发:
1.在开发前想一下,需要怎么来使用这个插件?肯定是new Tab(选择器),新建类后传入选择器,那如果想传递一些自定义的配置怎么做呢?
可以在html上加个data-config字段用于存放配置,然后使用getConfig()函数来获得
//index.html <div class="tab js-tab" data-config='{ "triggerType":"click", "effect":"fade", "invoke":1, "auto":3000 }'> //其他内容 </div> <script> $(function(){ var tab = new Tab($(".js-tab").eq(0)) }); </script>
//tab.js ;(function($){ var Tab = function(tab){ //这里写属性 }; Tab.prototype = { //这里写方法 } //把类挂载在全局 window.Tab = Tab; })(jQuery);
2.基础的结构写好了,接下来就是要处理配置,用户可能会传入参数也可能不会,所以默认参数是必须要提前来写好的,然后获得用户传入的参数,对比一下,看哪些写过哪些没写,把写过的保存,没写的使用默认项
如何实现呢?
使用jQuery.extend(),它用于合并对象,如果只为$.extend()指定了一个参数,则以前的配置舍弃直接用新的。如果多个对象具有相同的属性,则后者会覆盖前者的属性值
有了解决方法,可以直接来写了
;(function($){ var Tab = function(tab){ //这里写属性 var _this = this; // 保存单个tab组件 this.tab = tab; // 默认配置参数 this.config = { "triggerType":"mouseover", // 用来定义鼠标的触发类型,是click还是mouseover "effect":"default", // 用来定义内容切换效果,是直接切换还是淡入淡出效果 "invoke":1, // 默认展示第几个tab "auto":false // 定义tab是否自动切换,及自动切换时间间隔 }; // 如果配置参数存在,就扩展掉默认配置参数 if(this.getConfig()){ $.extend(this.config,this.getConfig()); } }; Tab.prototype = { //这里写方法 // 获取配置参数 getConfig: function(){ // 拿一下tab elem节点上的data-config var config = this.tab.attr("data-config"); // 确保有配置参数 if(config&&config!=""){ return $.parseJSON(config); }else{ return null; } } } //把类挂载在全局 window.Tab = Tab; })(jQuery);
测试一下,如果没有传参,会不会将默认配置写上:
再测试一下,如果传某几项参数,会不会将配置混合:
接着来开发,接下来就可以来添加一些事件交互效果了,有哪些效果呢?点击和鼠标滑过,先来看点击,要想点击肯定得先获取到点击的内容,就是在html写的li标签,this.tab.find("ul.tab_nav li")
同时当点击了li标签中的分类后,应该对应的显示不同的内容,所以这部分内容也要获取到,this.tab.find("div.content_wrap div.content_item")
然后判断属于点击事件还是鼠标滑过事件,为它添加上对应的样式和修改对应的内容,这个在invoke中实现,有了思路,直接来写:
;(function($){ var Tab = function(tab){ //前面内容省略 // 保存tab标签列表、对应的内容列表 this.tabItems = this.tab.find("ul.tab_nav li"); this.contentItems = this.tab.find("div.content_wrap div.content_item"); // 保存配置参数 var config = this.config; if(config.triggerType === "click"){ this.tabItems.bind(config.triggerType,function(){ _this.invoke($(this)); }) }else if(config.triggerType != "click"){ this.tabItems.bind("mouseover",function(){ _this.invoke($(this)); }) } }; Tab.prototype = { //这里写方法 //前面的省略 // 事件操作函数 invoke: function(currentTab){ var _this = this; var index = currentTab.index(); // tab选中状态 currentTab.addClass('active').siblings().removeClass('active'); // 切换对应的内容区域 var effect = this.config.effect; var conItems = this.contentItems; if(effect === "default" || effect != "fade"){ conItems.eq(index).addClass('current').siblings().removeClass('current'); }else if(effect === "fade"){ conItems.eq(index).fadeIn().siblings().fadeOut(); }; // 注意:如果参数配置了自动切换时间,要把当前的loop的值设置成当前tab的index if(this.config.auto){ this.loop = index; } }, } //把类挂载在全局 window.Tab = Tab; })(jQuery);
至此,应该能实现点击或鼠标滑过修改样式和更改内容,测试一下:
上面实现了手动的点击或者鼠标滑过时切换的功能,但实际的tab插件是有自动切换的功能,如何来实现呢?可以使用setInterval来实现,周期就是data-config中的auto,在回调函数中依次以点击或者鼠标滑过的方式来触发,如何实现依次调用?写个循环的变量this.loop = 0;如何自动触发呢?jquery有一个trigger方法,它就是用来自动触发选中的事件的,思路有了,开写:
;(function($){ var Tab = function(tab){ //前面内容省略 // 自动切换功能,如果配置了时间,我们就根据时间间隔进行自动切换 if(config.auto){ // 定义一个全局的定时器 this.timer = null; // 计数器 this.loop = 0; this.autoPlay(); } }; Tab.prototype = { //这里写方法 //前面的省略 // 自动间隔时间切换 autoPlay: function(){ var _this = this, tabItems = this.tabItems, // 临时保存tab列表 tabLength = tabItems.size(), // tab的个数 config = this.config; this.timer = window.setInterval(function(){ _this.loop ++; if(_this.loop >= tabLength){ _this.loop = 0; }; tabItems.eq(_this.loop).trigger(config.triggerType); },config.auto); }, } //把类挂载在全局 window.Tab = Tab; })(jQuery);
ok,测试一下,此时应该会自动的进行切换:
确实实现了自动切换,但是当鼠标放在上面的时候,它停不住,这个需要来解决一下,添加个hover,然后在悬浮的时候清除一下setInterval
this.tab.hover(function(){ window.clearInterval(_this.timer); },function(){ _this.autoPlay(); });
ok,搞定,在鼠标放上去的时候他会自动停止,移开后又自动的循环
终于到了最后一个功能,需要传入某个默认选择时,从该选择开始循环,这个有了前面的铺垫就好实现了,只需要简单设置一下就行了this.tabItems.eq(config.invoke-1)
;(function($){ var Tab = function(tab){ //前面内容省略 // 设置默认显示第几个tab if(config.invoke > 1){ this.invoke(this.tabItems.eq(config.invoke-1)); } }; Tab.prototype = { //这里写方法 //前面的省略 } //把类挂载在全局 window.Tab = Tab; })(jQuery);
测试一下,看看它会不会从第二个开始循环:
ok,所有的功能都实现了,是时候考虑一下用户使用的便捷性了,在上面使用这个插件的时候是通过 var tab = new Tab($(".js-tab").eq(0)) 这样来实现的,但是实际的插件使用应该是 Tab.init($(".js-tab"));或者$(".js-tab").tab();这样的来调用,就需要来把new的这个过程给封装卡来,each方法把传入的内容给都new一遍,或者$.fn.extend()直接把它加在jquery上,实现一下:
;(function($){ var Tab = function(tab){ //前面内容省略 }; Tab.prototype = { //前面的省略 } Tab.init = function(tabs){ var _this = this; tabs.each(function(){ new _this($(this)); }) } // 注册成jq方法 $.fn.extend({ tab: function(){ this.each(function(){ new Tab($(this)); }); return this; } }) //把类挂载在全局 window.Tab = Tab; })(jQuery);
测试一下:
ok,整个插件就做好了,做这个关键了解了封装jquery插件的流程,以后就可以自己来封装属于自己的jquery插件了。
这个过程,是学习自这个教程:https://www.imooc.com/learn/825,大家可以去看看。
完整代码下载:http://zuitingliu.com/?p=163