bootstrap源码jQuery插件之button.js源码分析笔记

架不住移动端的兼容的诱惑,bootstrap随着学习,它的强大以及可以让我学习的地方众多。今天又来写写button.js这个相对简单的按钮插件,写完这篇文章,估计我对js又有新的提高和巩固。本文只是作为本人笔记,看法,不保证对,也很肤浅,大神绕道。

个人认为知识点:jQuery插件:能够进一步学会如何封装某个js库的插件,能够学习更多平时不常用却比较重要的js语法基础

bootstrap的js源码:能够更好的理解bootstrap框架动态效果展示

bootstrap的css3和js的配合使用:它大量使用css3动画效果,transition,transform用的666


虽然bootstrap使用频率很高,也相对好用,但还是非常多人反对直接使用它,理由各式各样,但无可否认,它是最受欢迎的前端样式框架,既然大受欢迎,对于我这种菜鸟来说,还是值得好好研读。研究它的使用,研究它的源码,研究框架分工,各个分工的实现,less代码编译工具使用等等。

回归正题,buttonjs源码分析笔记开始。

首先jQuery插件通用写法,匿名立即执行函数,传入实参jQuery,形参$。这给我们一个启示,制作某个js库的依赖插件库,都是要传入那个js库的参数;由于js语言的特性,为了避免变量污染,都需要立即执行函数隔离变量,需要暴露的变量注册为全局变量。

+function($){
//........
}(jQuery);

严格模式:最直接的目的是逐步淘汰掉以前js语法中的糟粕;消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;消除代码运行的一些不安全之处,保证代码运行的安全;提高编译器效率,增加运行速度;为未来新版本的Javascript做好铺垫。随着es6标准的逐步落地实现,随着各个大项目,开源框架vue、 angular等使用es6,养成使用严格模式习惯,是非常重要的。

'use strict';

使用严格模式,会禁止使用某些关键字,变量必须事先var 声明等等,在某些程度上改变js原来的宗旨:宽松,动态,脚本。时过境迁,毕竟以前js承担任务不多,现在浏览器发展,前端作用越来越强,js做出限制以及增加是必须的,不过感觉越来越向强类型语言靠拢的感觉。

//button类构造函数
  var Button = function (element, options) {
    this.$element  = $(element)
    this.options   = $.extend({}, Button.DEFAULTS, options) //jQuery的扩展方法,插件必备:将options合并到Button.DEFAULTS中
    this.isLoading = false //是否加载
  }

$.extend是我们在写插件的过程中常用的方法,该方法有一些重载原型extend(dest,src1,src2,src3...) 

它的含义是将src1,src2,src3...合并到dest中,返回值为合并后的dest,由此可以看出该方法合并后,是修改了dest的结构的。如果想要得到合并的结果却又不想修改dest的结构,

可以如下使用:

var aa=$.extend({},{x:"x",y:'y'},{x:"x2",z:"z"})

结果展示

aa={x:'x2',y:'y',z:'z'}
也即是源码中的样子

this.options   = $.extend({}, Button.DEFAULTS, options) 
button的loading状态,通过获取button当中的value值或者html值,然后在loading时候将button设置为disabled=true,禁止点击等待下载,下载完毕允许点击
//设置button状态
  Button.prototype.setState = function (state) {
    var d    = 'disabled'  //禁用
    var $el  = this.$element
    var val  = $el.is('input') ? 'val' : 'html' //如果是input控件,存取input内容,否则存取html内容
    var data = $el.data()//data() 方法向被选元素附加数据,或者从被选元素获取数据。

    state += 'Text' //拼接Text字符串,便于理解字面意思

    if (data.resetText == null) $el.data('resetText', $el[val]())//如果data没有resetText绑定,则创建

    // push to event loop to allow forms to submit
    //$.proxy()该方法通常用于向上下文指向不同对象的元素添加事件。保证了this指向,避免作用域改变而导致错误
    setTimeout($.proxy(function () {
      $el[val](data[state] == null ? this.options[state] : data[state])

      if (state == 'loadingText') {
        this.isLoading = true
        $el.addClass(d).attr(d, d).prop(d, true)//添加class="disabled" disabled="true"
      } else if (this.isLoading) {
        this.isLoading = false
        $el.removeClass(d).removeAttr(d).prop(d, false)//移除上面添加的属性
      }
    }, this), 0)
  }

button切换,例如radio checkbox 和其它类型的input,把单选框和复选框分别区分,其它的都是输入框,判断完成

//按钮效果切换,radio checkbox 
  Button.prototype.toggle = function () {
    var changed = true
    var $parent = this.$element.closest('[data-toggle="buttons"]')//closest表示从this.$element开始检索拥有data-toggle="buttons"属性的标签
    //区分radio checkbox按钮,active是规定好的类样式
    if ($parent.length) {
      var $input = this.$element.find('input')
      if ($input.prop('type') == 'radio') {
        if ($input.prop('checked')) changed = false
        $parent.find('.active').removeClass('active')
        this.$element.addClass('active')
      } else if ($input.prop('type') == 'checkbox') {
        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
        this.$element.toggleClass('active')
      }
      $input.prop('checked', this.$element.hasClass('active'))
      if (changed) $input.trigger('change')
    } else {
      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))//arai盲人无障碍阅读属性
      this.$element.toggleClass('active')
    }
  }

bootstrap的button插件自定义:

① 暴露类名, 可以通过这个为插件做自定义扩展

// 扩展的方式
// 设置 : $.fn.button.Constructor.newMethod = function(){}
// 使用 : $btn.button("newMethod");

② 无冲突处理

③ 事件代理, 智能初始化

以上是开发自定义插件必要过程,由于没什么经验,具体不做分析,百度去吧

 // BUTTON PLUGIN DEFINITION
  // ========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this) //保存this作用域
      // 判断是否初始化过的依据
      var data    = $this.data('bs.button') //data() 方法向被选元素附加数据,或者从被选元素获取数据。
      var options = typeof option == 'object' && option //如果option为object类型和option参数值,返回true,否则返回false

      if (!data) $this.data('bs.button', (data = new Button(this, options)))// 如果没有初始化过, 就初始化它,为元素附加Button实例

      if (option == 'toggle') data.toggle()
      else if (option) data.setState(option)
    })
  }

  
  var old = $.fn.button 

  $.fn.button             = Plugin
  // ① 暴露类名, 可以通过这个为插件做自定义扩展
  $.fn.button.Constructor = Button


  // BUTTON NO CONFLICT
  // ==================
  //② 无冲突处理
  $.fn.button.noConflict = function () {
    $.fn.button = old
    return this
  }


  // BUTTON DATA-API
  // ===============
  // ③ 事件代理, 智能初始化
  $(document)
    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
      var $btn = $(e.target).closest('.btn')
      Plugin.call($btn, 'toggle')
      if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
        // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
        e.preventDefault()
        // The target component still receive the focus
        if ($btn.is('input,button')) $btn.trigger('focus')
        else $btn.find('input:visible,button:visible').first().trigger('focus')
      }
    })
    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
    })

虽然没有完全看懂,但也学到jQuery一些API的使用,知道bootstrap的button控制流程,下次继续研究,加油


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值