我爱编程

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

2018-07-25  本文已影响0人  潘千千
前言:最近公司后台需要实现一个类似于选项卡的一个搜索,比如说点击手机型号,下面出现很多选项如苹果华为等,点击其中一项,再下面一行会出现你点击的这个选项,当当当,就像下图这样:
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();
上一篇下一篇

猜你喜欢

热点阅读