Bootstrap插件解析4 按钮

2020-03-16  本文已影响0人  波拉拉

1 使用方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap 101 Template</title>

    <link href="bootstrap.css" rel="stylesheet">
    <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
</head>
<body>
<button type="button" class="btn btn-primary" data-toggle="button" >
    按钮切换
</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="bootstrap.js"></script>

<script>
</script>
</body>
</html>

2 整体结构

(function ($) {
    //构造函数
    var Button = function (element, options) {};
    // 静态变量
    Button.VERSION  = '3.3.7';
    //原型方法
    Button.prototype.setState = function (state) {};
    Button.prototype.toggle = function () {};
    //插件入口
    function Plugin(option) {}
    //防冲突处理
    $.fn.button.noConflict = function () {};
    //data-api实现
    $(document)
        .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {}
})(jQuery);

3 插件入口

function Plugin(option) {
    return this.each(function () {
      var $this   = $(this);
      var data    = $this.data('bs.button');//读取自定义数据
      var options = typeof option == 'object' && option;//是对象就保存
        //第一次实例化保存进自定义数据
      if (!data) $this.data('bs.button', (data = new Button(this, options)));
      //字符串toggle,执行方法
      if (option == 'toggle') data.toggle();
      else if (option) data.setState(option)
    })
  }
  var old = $.fn.button;
  //暴露插件了,静态变量指向原构造函数
  $.fn.button             = Plugin;
  $.fn.button.Constructor = Button;
  //  防冲突处理
  $.fn.button.noConflict = function () {
    $.fn.button = old;
    return this
  };

4 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))
    })

5 构造函数+静态变量

 var Button = function (element, options) {
    this.$element  = $(element);
    this.options   = $.extend({}, Button.DEFAULTS, options);//合并参数
    this.isLoading = false;
  };

  Button.VERSION  = '3.3.7';//插件版本

  Button.DEFAULTS = {
    loadingText: 'loading...'
  };//默认选项

6 原型方法

  Button.prototype.setState = function (state) {
    var d    = 'disabled';
    var $el  = this.$element;
    var val  = $el.is('input') ? 'val' : 'html';
    var data = $el.data();

    state += 'Text'

    if (data.resetText == null) $el.data('resetText', $el[val]())

    // push to event loop to allow forms to submit
    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)
      } else if (this.isLoading) {
        this.isLoading = false
        $el.removeClass(d).removeAttr(d).prop(d, false)
      }
    }, this), 0)
  }
  //切换方法
  Button.prototype.toggle = function () {
    var changed = true;//状态标识
    var $parent = this.$element.closest('[data-toggle="buttons"]')//找到切换按钮
    //处理单选框和复选框
    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'));
      this.$element.toggleClass('active')
    }
  };
上一篇下一篇

猜你喜欢

热点阅读