zoukankan      html  css  js  c++  java
  • bootstrap插件学习-bootstrap.tab.js(读码)

    先看bootstrap-tab.js的结构

    var Tab = function ( element ) {} //构造器
    Tab.prototype ={} //构造器的原型
    $.fn.tab = function ( option ){} //jQuery原型上自定义的方法
    $.fn.tab.Constructor = Tab //重写jQuery原型上的自定义方法的构造器名
    $(function () {}) //初始化

    HTML结构

    <ul class="nav nav-tabs">
        <li class="active"><a href="#home" data-toggle="tab" >首页</a></li>
          <li><a href="#profile" data-toggle="tab">介绍</a></li>
          <li><a href="#messages" data-toggle="tab">消息</a></li>
          <li><a href="#settings" data-toggle="tab">设置</a></li>
    
    </ul>
    
    <div class="tab-content">
      <div class="tab-pane active" id="home">1</div>
      <div class="tab-pane" id="profile">2</div>
      <div class="tab-pane" id="messages">3</div>
      <div class="tab-pane" id="settings">4</div>
    </div>

    先从初始化开始

    /*
      * 初始化
      * 给拥有data-toggle='tab'属性的标签绑定click事件
      * */
      $(function () {
        $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
          e.preventDefault()
          $(this).tab('show')//向jQuery原型方法tab传入参数show,应该执行show方法。this为拥有data-toggle属性的a标签对象
        })
      })

    让body监听a标签的click事件,并且阻止其冒泡,调用了jQuery的原型方法tab。

    /*
      * jQuery原型上自定义的方法
      * */
      $.fn.tab = function ( option ) {
        return this.each(function () {
          var $this = $(this)
            , data = $this.data('tab')
          if (!data) $this.data('tab', (data = new Tab(this)))//实例化构造器
          if (typeof option == 'string') data[option]()//执行option的方法
        })
      }

    这个结构跟之前的几个插件差不多,不过最后它是执行了show方法的,进入构造器

    var Tab = function ( element ) {
        this.element = $(element)
      }

    将对象封装成构造器实例的一个属性。接下来我们执行show方法

    show: function () {
          var $this = this.element
            , $ul = $this.closest('ul:not(.dropdown-menu)')//找到最近的不是dropdown类的ul元素
            , selector = $this.attr('data-target')
            , previous
            , $target
          //获取与a标签对应的内容id
          if (!selector) {
            selector = $this.attr('href')
            selector = selector && selector.replace(/.*(?=#[^s]*$)/, '') //strip for ie7
          }
          //如果一直点击自己,这句之后的代码将不执行
          if ( $this.parent('li').hasClass('active') ) return
    
          previous = $ul.find('.active a').last()[0]//获得拥有active类的原生a标签对象,即上一次高亮的节点
    
          $this.trigger({
            type: 'show'
          , relatedTarget: previous
          })
    
          $target = $(selector)//获得内容节点的jQueryDOM对象
    
          this.activate($this.parent('li'), $ul)//tab页切换
    
    
          this.activate($target, $target.parent(), function () {
            $this.trigger({
              type: 'shown'
            , relatedTarget: previous
            })
    
          })

    根据标签a的data-target属性或是其href找到对应的id的dom节点。最后我们执行了两次activate方法,其实大概猜的出来,一个方法控制a标签的高亮显示,另一个控制dom节点的显示与隐藏

    /*
        * 控制显示与隐藏
        * 参数主要形式是这样的,一个是可以拥有active类的元素,另一个是其父类。
        * 先找到父类下来所有拥有active类的节点,删除它们的active,并将当前节点,也就是第一个参数加上active类。
        *
        * */
      , activate: function ( element, container, callback) {
    
          var $active = container.find('> .active')
            , transition = callback
                && $.support.transition//需要引入其他js文件,这里没有引入。
                && $active.hasClass('fade')
          console.log($active[0])
          function next() {
            $active
              .removeClass('active')
              .find('> .dropdown-menu > .active')
              .removeClass('active')
    
            element.addClass('active')
    
            if (transition) {
              element[0].offsetWidth // reflow for transition
              element.addClass('in')
            } else {
              element.removeClass('fade')
            }
    
            if ( element.parent('.dropdown-menu') ) {
              element.closest('li.dropdown').addClass('active')
            }
    
            callback && callback()
          }
    
          transition ?
            $active.one($.support.transition.end, next) :
            next()
    
          $active.removeClass('in')
        }

    逻辑比较简单,一般遇到一个显示其他同类不显示的情况,基本都是这一套方法,增删class来达到要求。但对于jQuery操作css完成class切换与javascript原生方法相比,哪个效率会更好一点呢?也希望有经验的园友给予解答。

    另外是部分css,表现了两块active类的作用

    /*tab页切换时的active作用*/
    .nav-tabs > .active > a,
    .nav-tabs > .active > a:hover,
    .nav-tabs > .active > a:focus {
      color: #555555;
      cursor: default;
      background-color: #ffffff;
      border: 1px solid #ddd;
      border-bottom-color: transparent;//将底部边框变透明
    }
    
    /*dom*/
    
    .tab-content > .tab-pane,
    .pill-content > .pill-pane {
      display: none; //原来为隐藏
    }
    
    .tab-content > .active,
    .pill-content > .active {
      display: block; //加入active ,变为显示
    }

     

     

    文实例为大家介绍实现tab选项卡的应用,此插件相对比较简单,具体内容如下
    源码文件:
    tab.js

    实现原理:
    1、单击一个元素时,首先将原来高亮的元素取消
    2、然后给被单击元素进行高亮
    3、如果单击元素是下拉框中某个选项,则选中本身,还要选中下拉框
    5、如果定义了动画,先执行动画,然后回调

    源码分析:
    1、Show方法,是在单击一个元素的时候触发,会触发如下四个事件
      1.1、Hiden.bs.tab:隐藏上一个元素
      1.2、Show.bs.tab:显示当前元素
      1.3、Hideen.bs.tab:隐藏上一个元素完成
      1.4、Shown.bs.tab:显示当前元素完成
      1.5、Hiden/show事件源码:

    1
    2
    3
    4
    5
    6
    7
    var $previous = $ul.find('.active:last a')
     var hideEvent = $.Event('hide.bs.tab', {
     relatedTarget: $this[0]
     })
     var showEvent = $.Event('show.bs.tab', {
     relatedTarget: $previous[0]
    })

    2、Active:激活当前对象
      2.1、对导航元素增加aria-expanded属性,标记此元素是否处于展开状态
      2.2、利用reflow机制,用获取offsetWidth属性来实现部分重绘

  • 相关阅读:
    WebView(网页视图)基本用法
    Android——ProgressBar(进度条)
    第一阶段任务
    第七周学习总结
    (HDU)1095 --A+B for Input-Output Practice (VII)(输入输出练习(VII))
    (HDU)1094 --A+B for Input-Output Practice (VI)(输入输出练习(VI))
    (HDU)1093 --A+B for Input-Output Practice (V)(输入输出练习(V))
    (HDU)1092 --A+B for Input-Output Practice (IV)(输入输出练习(IV))
    (HDU)1091 --A+B for Input-Output Practice (III)(输入输出练习(III))
    (HDU)1090 --A+B for Input-Output Practice (II)(输入输出练习(II))
  • 原文地址:https://www.cnblogs.com/wdcwy/p/6540829.html
Copyright © 2011-2022 走看看