jquery插件的封装过程。
jquery插件封装
使用过很多的jquery的插件,但是不了解它们到底是怎样做的,今天就来封装一个最常见的tab插件,看看具体的封装过程。
tip:完整代码下载在最后面,需要的直接跳过去看
1.html结构
常见的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>
它是长这个样子,够丑,下一步来美化一下:
2.css样式
引入个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;
}
它就长成这个样子了,看着舒服多了,马上进行下一步,插件封装:
3.js逻辑
3.1基本结构
在封装插件前,先来引入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);
3.2配置参数
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);
测试一下,如果没有传参,会不会将默认配置写上:
再测试一下,如果传某几项参数,会不会将配置混合:
3.3事件交互
接着来开发,接下来就可以来添加一些事件交互效果了,有哪些效果呢?点击和鼠标滑过,先来看点击,要想点击肯定得先获取到点击的内容,就是在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);
至此,应该能实现点击或鼠标滑过修改样式和更改内容,测试一下:
3.4自动切换
上面实现了手动的点击或者鼠标滑过时切换的功能,但实际的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,搞定,在鼠标放上去的时候他会自动停止,移开后又自动的循环
3.5默认选项
终于到了最后一个功能,需要传入某个默认选择时,从该选择开始循环,这个有了前面的铺垫就好实现了,只需要简单设置一下就行了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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。