来,让我们用prototype和jq封装一个简单的tab小插件吧

前言:最近公司后台需要实现一个类似于选项卡的一个搜索,比如说点击手机型号,下面出现很多选项如苹果华为等,点击其中一项,再下面一行会出现你点击的这个选项,当当当,就像下图这样:
image.png

  点击搜索按钮,会收集选择结果那一行需要的数据传递给后台。由于这种形式的搜索在其他页面还会出现很多,所以,需要我把他们进行一下封装,前提是从后台接收到的数据结构都是一样的。

关键词:$.fn $.extend prototype 选项卡 封装 ......

正文:
1、需求:
运营提了要求,像很多插件一样,当他们想要用的时候,只需要在html里面写一个带有class的div,在script里面写入function然后传入数据就行:

html:
......
<div class="box"> </div>
......
script:
......
$('.box').tagRel({
     data:${dataValue}
 });
......
js:
(function($,window){
 function tagRel(element,options){
     this.element = $(element);
     this.options = $.extend({}, options);
     this._createDom();
     this._tabInit();
     this._tabToggle();
     this._labelClick();
     this._chosenClose();
 }
 tagRel.prototype = {
     //0:createDom
     _createDom : function(){
         var data = this.options.data,//要循环的数组
             divHiddenForm = '',//隐藏域,放在this.element的前面
             diva= '',
             divb= '',
             divc= '',
             divaLi = '',//diva的tabli
             divbPane = '';//divb的tab-pane
             //divbPaneLi = '';//divb的tab-pane-li
         divHiddenForm = '<form id="searchForm" method="post" style="display:none">' +
                             '<table class="search-table">' +
                                 '<tr>' +
                                     '<th>标签名称:</th>' +
                                     '<td><input id="hidden" name="condition" type="text"/></td>' +
                                 '</tr>' +
                             '</table>' +
                         '</form>';
         //循环divaLi,divbPane
         $.each(data,function(i,item){
             ......(省略)
         })
         diva = '<div class="title-box clearfix">'+
                     '<span class="labelValue">标签:</span>'+
                     '<ul class="tab-nav">'+divaLi+'</ul>'+
                 '</div>';
         divb = '<div class="tab-content">'+divbPane+'</div>';
         divc = '<div class="tab-footer clearfix">'+
                 '<span class="labelValue">选择结果:</span>'+
                 '<ul class="chosen-box"></ul>'+
               '</div>';
         //1:this.element之前放入隐藏域
         this.element.before(divHiddenForm);
         //2:this.element里面放入tab-title-box
         this.element.append(diva);
         //3:this.element里面放入tab-content-box
         this.element.append(divb);
         //4:this.element里面放入tab-chosen-box
         this.element.append(divc);
     },
     //1:tab初始化
     _tabInit : function(){
         $('.tab-li').eq(0).addClass('active');//第一个标签默认选中#
         $('.tab-pane').eq(0).stop().fadeIn();//第一个div默认显示
     },
     //2:tab切换
     _tabToggle : function(){
         var self = this;
         $('.tab-li').click(function(e){
             var liIndex = $(this).index();
             $(this).addClass('active');
             $(this).siblings().removeClass('active');
             $('.tab-pane').hide();
             $('.tab-pane').eq(liIndex).stop().fadeIn();
         })
     },
     //3:label点击
     _labelClick : function(e){
         ...(省略,这里就是一个点击标签,下层结果出现标签的效果)
     },
     //4:chosenClose关闭
     _chosenClose : function(e){
         var self= this;
         $(".layui-tab-close").live('click',function(e){
             e.stopPropagation();
             var dataId = $(this).closest('li').attr('data-id');
             var targetli = $('.tab-content').find('li[data-id='+dataId+']');
             targetli.removeClass('active');
             $(this).closest('li').remove();
             self._collection();
         })
     },
     //5:collect:收集结果
     _collection:function(){
         //收集信息
         var arr = [];
         $('.chosen-box li').each(function(){
             var key = $(this).attr('data-tag'),
                 keyValue =$(this).attr('data-val'),
                 json = {};
             json.tagName = key;
             json.tagValue = keyValue;
             arr.push(json);
         })//console.log(arr);//最终传输数据。
         $('#hidden').val(JSON.stringify(arr));
     }
 }

 $.fn.tagRel = function(options){
     new tagRel(this,options);
 }

})(jQuery,window);

好,上面是代码,下面就是几行重要代码的解析:
先看下面这张图片,比较直观:


image.png

这张图片是上述代码收缩了部分,比较能够突出我要说的重点:

重点一:

我们用写插件的人的思维来思考,我们肯定是需要一个函数的,这个函数要接受到script里面传过来的参数。所以,我们先写一个函数。就是上图中的函数一。
函数一接收了两个参数。一个是element,一个是options。element就代表着script里面是是哪个标签触发了这个函数,就是那个$(),里面是class。而options就是接收到的数据。

重点二:

$.extend({},options):
$.extend()有两种用法
  一种是扩展方法。
  另一种是合并对象获得一个新的对象。
这里,我们介绍一下合并对象这个方法:
一般的插件中,比如说拖拽插件,表格插件,都会有一些默认的参数,那是在具体实例化时数据参数未传进来的时候,这些默认的参数不会让展示出来的页面看起来垮掉,哈哈。
下面是找到的两个插件的默认参数default:
拖拽插件:


image.png

表格插件:


image.png

大家是否觉得有点不一样,其实,细心的人发现,本质上两个是一样的,只不过表格插件是合起来写了。
例如:
        var settings={validate:false,limit:5,name:"sm"};
        var defaults={validate:true,limit:2}
        var settings=$.extend(defaults,settings);
        结果:settings={validate:false,limit:5,name:"sm"}
重点三:

现在有了函数了,那么我们对于这个tab的一些操作都写在哪里呢,写在原型里吧,可随时取用。

重点四:

封装起来就可以了吗?不行的,因为我们每次传参数使用的时候是一个实例:
所以,最后那个函数的意思如下:
$.fn是指jquery的命名空间,加上fn上的方法及属性,会对jquery实例每一个有效。如扩展$.fn.abc()。
在 jQuery 中,fn 其实就是 JavaScript 中 propotype 的一个别名,$ 是 jQuery 的别名,所以
$.fn.tagRel等同于 jQuery.prototype.pluginName。举个简单的小例子:
('li') 是一个对象,它的 key 有 length,它的原型(共享属性)为 jQuery.prototype,jQuery.prototype 的 key 有 addClass、removeClass、text、html 和 on 等。 \.fn.tagRel表示创建一个 jQuery 的属性,通俗的说是写一个 jQuery 函数,tagRel才是函数名
eg:

$.fn.setRedText = function() {
    return $(this).css("color", "red");
};
$("p").setRedText();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容