bootstrap插件学习-bootstrap.collapse.js

时间:2022-10-02 12:47:44

先看bootstrap.collapse.js的结构

var Collapse = function ( element, options ){} // 构造器
Collapse.prototype = {} //构造器的原型
$.fn.collapse = function ( option ){} //jQuery原型上自定义的方法
$.fn.collapse.defaults = {} // 默认参数
$.fn.collapse.Constructor = Collapse // 重写jQuery原型自定义方法的构造器名
$(function (){}) // 初始化

HTML结构

<div class="accordion" id="accordion2">

     <div class="accordion-group">

       <div class="accordion-heading">

         <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">

           国土问题

         </a>

       </div>

       <div id="collapseOne" class="accordion-body collapse" style="height: 0px;">

         <div class="accordion-inner">

   前一段时间一个段子说,某国的网民在因国土问题与中国网民争吵时说,我要打到北京,中国的网民非常淡然地回应,就你那经济水平,交得起过路费吗?这两天新的段子说,李白要是活在今天的话,估计一大半以上他的诗根本写不出来,因为名山大川的门票他根本买不起。

         </div>

       </div>

     </div>

     <div class="accordion-group">

       <div class="accordion-heading">

         <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseTwo">

           门票问题

         </a>

       </div>

       <div id="collapseTwo" class="accordion-body collapse" style="height: 0px;">

         <div class="accordion-inner">

   目前,中国半数5A级景区门票达到100元,黄山门票10年来由80元涨至230元。山东曲阜称,与同类景区相比收费较低,仅收150元,不涨票价就丢身价。曲阜的孔庙、孔府和孔林,年收入1.5亿元左右,全部上缴了地方财政,但景区维护成本从未公开。

         </div>

       </div>

     </div>

     <div class="accordion-group">

       <div class="accordion-heading">

         <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseThree">

           超生罚款

         </a>

       </div>

       <div id="collapseThree" class="accordion-body in" style="height: auto;">

         <div class="accordion-inner">

   学者杨支柱因生二胎被取消公职,并罚款24万余元。他称,计生罚款以前直接叫超生罚款,入世后改成"社会抚养费"。根据9省市超生罚款的平均数,全国31个省市每年征收的超生罚款可高达279亿元。其中大城市将该收入上缴财政,而地方则分配混乱,部分罚款去向成谜。

         </div>

       </div>

     </div>

   </div>

我们先从初始化开始

/*
* 初始化
* */
$(function () {
$('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { var $this = $(this), href
, target = $this.attr('data-target')//标题没有data-target属性,阻止冒泡
|| e.preventDefault()
|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
//根据点击的标题,获取相对应内容的id
, option = $(target).data('collapse') ? 'toggle' : $this.data()//初次执行时$(target)没有collapse属性
$(target).collapse(option)
})
})

body监听了所有拥有data-toggle='collapse'属性的标签,为它们绑定了click事件,在HTML中由于标签上都没有data-target属性,所以该事件被阻止冒泡,最后获得点击标题框所对应的内容div的id。

当我们刷新页面,第一次点击时,由于$(target).data('collapse')为空,所以option为$this.data()的内容,主要有{parent:'#accordion2',toggle:'collapse'},下面执行jQuery对象上的collapse方法

/*
* jQuery原型上自定义的方法
* */
$.fn.collapse = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('collapse')
, options = typeof option == 'object' && option
if (!data) $this.data('collapse', (data = new Collapse(this, options)))//实例化构造器
if (typeof option == 'string') data[option]()//支持传入方法名,执行该方法
})
}

此时调用collapse方法的是你点击标题框所对应的内容div,这里我们需要初始化构造器。因为option此时为对象,所以最后一句不执行。

/*
* 构造器
* */
var Collapse = function ( element, options ) {
this.$element = $(element)
this.options = $.extend({}, $.fn.collapse.defaults, options)
if (this.options["parent"]) {
this.$parent = $(this.options["parent"])//获取整个控件的jQuery对象
}
this.options.toggle && this.toggle()//实例化执行原型上的toggle方法
}

这里this.$parent指的是整个控件的div,id为'#accordion2',执行原型上的toggle方法

toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()//实例化初次执行show方法
}

这里,查看内容div上是否有in类,其实bootstrap.collapse插件,在显示的内容上,会有in类,不显示的内容上会collapse类,不过,之前我们先了解。这个插件刷新时,第三块内容显示,ok,我们点击第一块试一试。,那么第一块对应的内容div就没有in类,所以我们执行show方法,在进入方法之前,我们可以想想下面插件需要完成的步骤:1。将之前显示的隐藏了 2.显示被点击的

/*
* 显示方法
* */
, show: function () {
var dimension = this.dimension()
, scroll = $.camelCase(['scroll', dimension].join('-')) //'scrollHeight'
, actives = this.$parent && this.$parent.find('.in')//刷新时,显示内容的div,默认设置的
, hasData
if (actives && actives.length) {
//console.log(actives.data('collapse'));
hasData = actives.data('collapse')
actives.collapse('hide')//将开始显示的内容隐藏了,调用hide方法。
hasData || actives.data('collapse', null)
} this.$element[dimension](0)//将高度清0,完成隐藏效果
this.transition('addClass', 'show', 'shown')
this.$element[dimension](this.$element[0][scroll])//将当前点击的标签相关联的内容的高度恢复,结果显示效果 }

查看show方法之前,我们先看dimension方法

dimension: function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}

主要返回字符串,这个插件主要是上下显示隐藏,也可以左右隐藏。这里我们返回height

scroll = $.camelCase(['scroll', dimension].join('-')) //'scrollHeight'

目的将scroll与height两个字符串合并成scrollHeight。这种方式,我们可以了解一下。

actives = this.$parent && this.$parent.find('.in')//刷新时,显示内容的div,默认设置的

找到页面上目前显示的内容对象,经过if判断之后,这个内容对象调用了jQuery原型上的collapse方法。参数为hide,我们再次进入jQuery原型方法

/*
* jQuery原型上自定义的方法
* */
$.fn.collapse = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('collapse')
, options = typeof option == 'object' && option
if (!data) $this.data('collapse', (data = new Collapse(this, options)))//实例化构造器
if (typeof option == 'string') data[option]()//支持传入方法名,执行该方法
})
}

这里的$this.data('collapse')是没有,这个跟之前的要区分开来,之前的是你点击的想让它显示的内容,而现在这个是页面上原来就显示的内容。所以再一次的实例化。options内容为false。别忘了,执行完初始化之后再执行data[option],先看构造器

/*
* 构造器
* */
var Collapse = function ( element, options ) {
this.$element = $(element)
this.options = $.extend({}, $.fn.collapse.defaults, options)
if (this.options["parent"]) {
this.$parent = $(this.options["parent"])//此时已经没有该对象了
}
this.options.toggle && this.toggle()//实例化执行原型上的toggle方法
}

记住此时实例化的对象是当前显示的div内容。假如我们点击的是第一个标题对应的div,默认显示是第三个div,那这时实例化的对象就是第三个div。下面的代码分析,我们就这套看。

toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()//实例化初次执行show方法
}

此时的this.$element上已经拥有了in类,毕竟它是默认显示的嘛,执行原型上的hide方法。

/*
* 隐藏方法
* */
, hide: function () {
var dimension = this.dimension()
this.reset(this.$element[dimension]())
this.transition('removeClass', 'hide', 'hidden')
this.$element[dimension](0)//将高度清0
}

dimension这个就不重复说了,进入reset方法

reset: function ( size ) {
var dimension = this.dimension()
this.$element.removeClass('collapse')[dimension](size || 'auto')[0].offsetWidth//这句蛋疼
this.$element[size ? 'addClass' : 'removeClass']('collapse')//给要隐藏的内容div加上collapse样式 return this
}

想一想之前我们点击第一个div,目的是让它显示,隐藏其他div。这边调用reset方法的是div3,根据它的高度,增加collapse,前面我们也说了,bootstrap.collapse插件在隐藏的div上都加有collapse类,显示的div上都有in类,因为reset方法是根据高度来判断是否要添加class,所以在代码后面也肯定会将高度清0的,为的是依靠判断再次删去class,但是感觉这个方式太繁琐,通过高度判断,删减css让div隐藏,在将div的高度清0,再通过高度判断,向div上删减css样式,使其显示,最后在恢复div的高度。如此反复。

不多废话,进入transition方法

transition: function ( method, startEvent, completeEvent ) { //'removeClass','hide','hidden'
var that = this
, complete = function () {
if (startEvent == 'show') that.reset()
that.$element.trigger(completeEvent)
} this.$element
.trigger(startEvent)
[method]('in')//隐藏内容,并去掉in类 $.support.transition && this.$element.hasClass('collapse') ?
this.$element.one($.support.transition.end, complete) :
complete()
}

果不其然,就是如此实现的。

此时hide方法执行完毕,下面执行jQuery原型上的最后一句代码

if (typeof option == 'string') data[option]()//支持传入方法名,执行该方法

如果你们还记得,这个data,依旧是与div3有关的实例化对象。再次执行原型上的hide方法,这是这个插件我认为蛋疼的一个地方,插件的API没有很好的跟jQuery原型绑定上,仅仅依靠调用jQuery原型方法,实例化构造器去调用原型方法。导致jQuery队形不能直接使用原型上的方法,作者这样做的原因也有可能是防止自己在原型上定义的方法名和jQuery方法重名。遭到覆盖。不过换个名字,可能就解决了么。。。

再执行一遍hide,就不演示了,ok整个actives.collapse('hide')执行完毕,继续看show方法。

hasData || actives.data('collapse', null)//将data的collapse再次重新清空

将所有与actives有关的记忆全部删除。

this.$element[dimension](0)//将高度清0,
this.transition('addClass', 'show', 'shown')
this.$element[dimension](this.$element[0][scroll])//将当前点击的标签相关联的内容的高度恢复,结果显示效果

上面的代码,先清空div1的高度,在通过transition方法加入in类,最后恢复div1的高度,蛋疼。。

上述主要描述了div3显示,点击div1的情景,如果我们要点击div3,让它自己隐藏,让我们来看看代码过程。

我们点击div3,进入jQuery的collapse方法

/*
* jQuery原型上自定义的方法
* */
$.fn.collapse = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('collapse')
, options = typeof option == 'object' && option
if (!data) $this.data('collapse', (data = new Collapse(this, options)))//实例化构造器
if (typeof option == 'string') data[option]()//支持传入方法名,执行该方法
})
}

进入构造器

/*
* 构造器
* */
var Collapse = function ( element, options ) {
this.$element = $(element)
this.options = $.extend({}, $.fn.collapse.defaults, options)
if (this.options["parent"]) {
this.$parent = $(this.options["parent"])//获取整个控件的jQuery对象
}
this.options.toggle && this.toggle()//实例化执行原型上的toggle方法
}

好吧,进入toggle方法

toggle: function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()//实例化初次执行show方法
}

此时对象本身拥有in类,所以执行hide方法,ok,搞定。

其实这个插件还有几种情况,这里就不一一演示了。

没有很好的绑定jQuery原型,导致调用方法,实例化两次构造器,使得我们走代码的流程比较多,有点耐心,应该没问题。

内容不多,时间刚好,以上是我的一点读码体会,如有错误,请指出,大家共通学习。

bootstrap插件学习-bootstrap.collapse.js的更多相关文章

  1. bootstrap插件学习-bootstrap&period;dropdown&period;js

    bootstrap插件学习-bootstrap.dropdown.js 先看bootstrap.dropdown.js的结构 var toggle = '[data-toggle="drop ...

  2. bootstrap插件学习-bootstrap&period;modal&period;js

    bootstrap插件学习-bootstrap.modal.js 先从bootstrap.modal.js的结构看起. function($){ var Modal = function(){} // ...

  3. bootstrap插件学习-bootstrap&period;typehead&period;js

    先看bootstrap.typehead.js的结构 var Typeahead = function ( element, options ){} //构造器 Typeahead.prototype ...

  4. bootstrap插件学习-bootstrap&period;carousel&period;js

    先看bootstrap.carousel.js的结构 var Carousel = function (element, options){} //构造器 Carousel.prototype = { ...

  5. bootstrap插件学习-bootstrap&period;alert&period;js

    我们先看bootstrap.alert.js的结构 var dismiss = '[data-dismiss="alert"]' //自定义属性 Alert = function ...

  6. bootstrap插件学习-bootstrap&period;button&period;js

    先看bootstrap.button.js的结构 var Button = function ( element, options ){} //构造器 Button.prototype = {} // ...

  7. bootstrap插件学习-bootstrap&period;popover&period;js

    先看bootstrap.popover.js的结构 var Popover = function ( element, options ){} //构造器 Popover.prototype = {} ...

  8. bootstrap插件学习-bootstrap&period;tooltip&period;js

    先看bootstrap-tooltip.js的结构 var Tooltip = function ( element, options ){} // 构造器 Tooltip.prototype ={} ...

  9. bootstrap插件学习-bootstrap&period;scrollspy&period;js

    先看bootstrap.dropdown.js的结构 function ScrollSpy(){} //构造函数 ScrollSpy.prototype = {} //构造器的原型 $.fn.scro ...

随机推荐

  1. 用css改变默认的checkbox样式

    自己常用的改变checkbox样式的两个方法: 一.利用background用图片代替checkbox效果 缺点:你首先得有一张好看的图片 优点:浏览器兼容性好 <!doctype html&g ...

  2. MySQL 备份与恢复

    一.备份/恢复策略 考虑因素有: (A) 表的存储引擎是否事务性的,在数据一致性方面不太一样. (B) 确定是全备份还是增量备份, (C) 考虑采取复制的方法做异地备份,复制不能代替备份 (D) 定期 ...

  3. PHP设计模式之装饰者模式

    <?php /* 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. */ header("Content-type:text/html; cha ...

  4. TP复习2

    ## ThinkPHP 3.1.2 输出和模型使用#讲师:赵桐正微博:http://weibo.com/zhaotongzheng 本节课大纲:M() 等效为 new Model();$m=M('Us ...

  5. Android开源git40个App源码

    http://www.itbbu.com/1039.html (JamsMusicPlayer)很棒的音乐播放器(new)   (F8)日程安排的软件   (Conversations)基于XMPP的 ...

  6. Java基础知识强化90:Date类之Data类中日期和毫秒相互转换

    1.Date两个方法: public long getTime():获取时间,以毫秒为单位 public void setTime(long time):设置时间 2. 代码示例: package c ...

  7. MD5加密字符串-备用

    @interface NSString (MyExtensions) - (NSString *) md5; @end @implementation NSString (MyExtensions) ...

  8. 用phpMyAdmin修改mysql数据库密码

    1初始数据库密码为空. 2第一步,点击phpMyAdmin里的用户选项. 3选择root localhost用户名,点击编辑权限. 4此时会出来修改权限的页面,里面可以设置的选项还是比较多的,暂时不管 ...

  9. HP 3par多路径安装方法

    一.Linux下multipath介绍,需要以下工具包: 在CentOS 5中,最小安装系统时multipath已经被安装,查看multipath是否安装如下: 1.device-mapper-mul ...

  10. win10 关闭自动更新

    方法一 : 利用组策略关闭win10自动更新的步骤如下:1.按win+R打开“运行”,输入“gpedit.msc”,按下回车. 2.找到“计算机配置”→““管理模板”→“Windows 组件”→“Wi ...