jquery插件select2.js源码解读【概述,流程,options】

概述

在使用select2插件之前,我们需熟悉相关的js框架,当然jquery必不可少。其中涉及部分框架比如:gruntfilerequirejs.当然在这里只用到了requi这里写代码片rejs的部分功能。
先看一个简单的实例:从select2(当前版本4.0.3)官网下载源码,解压后,抽取相应的js和css文件。目录结构如下:

这里写图片描述

src文件夹可忽略(后面源码分析主要为了看代码方便分析),下面是index.html的内容:

<!doctype html>
<html>
  <head>
    <link rel="stylesheet" href="select2.css" type="text/css" />
  </head>
  <body>
    select2测试:<select class="select2-container" name="test" id="test" style="width:180px;">
      <option value="test1">test1</option>
      <option value="test2">test2</option>
      <option value="test3">test3</option>
      <option value="test4">test4</option>
      <option value="test5">test5</option>
    </select> 
  </body>
  <script src="jquery-2.1.0.js" type="text/javascript"></script>
  <script src="select2.full.js" type="text/javascript"></script>
  <script type="text/javascript">
      $('#test').select2();
  </script>
</html>

测试界面展示:
这里写图片描述

当然这里只是做了简单的展示,其他功能在官网都可以看到。
接下来主要分析插件源码,其中包括:

1:select2整个生成及运行的流程。
2:理解观察者模式的运用。
3:javascript原型方法的运用。
4:整个插件的设计的思考和总结。


流程

在上篇文章中提到的目录结构中有src文件夹这便是select2 -4.0.3的源码文件,目录结构我们可以看到:
这里写图片描述

在这里只找些核心的js进行分析:那么就让我们看看整个流程吧。
从文件中我们可以看到core.js,从中我们可以了解到基本流程:

1:通过requirejsdefine方法把依赖模块注入到方法中,以便后面方法调用。
2:初始化options,其实options就是插件的一些参数配置。
3:初始化插件容器。
4:初始化选择适配器,生成selection相关页面元素并定位。
5:初始化下拉适配器,生成下拉相关页面元素并定位。
6:初始化结果适配器,生成结果相关页面元素并定位。
7:绑定适配器。
8:绑定相关事件。

这样整个流程就完了。


options

在这一小节,我们开始详细的阐述select2插件是怎么从初始化到生成的。

看代码:

define([
  'jquery',
  './options',
  './utils',
  './keys'
], function ($, Options, Utils, KEYS) {
//....
})

使用过requirejs的都知道define方法的使用。从上面的代码可以看出,该方法把依赖的模块jquery,options,utils,keys注入到下面的方法中,并且模块和参数是一一对应关系,并且顺序一致。jquery想必大家都很熟悉,那么后面三个模块我们看代码吧^^.

先看看整体结构:

var Select2 = function ($element, options) {//初始化插件
     if ($element.data('select2') != null) {
     $element.data('select2').destroy();
     }
    //code…
    $element.data('select2', this);
  };
Utils.Extend(Select2, Utils.Observable);//观察者模式
Select2.prototype._generateId = function ($element) { };
Select2.prototype._placeContainer = function ($container) { };
//code select2原型链方法
//…
//…
 Select2.prototype.destroy = function () {};
Select2.prototype.render = function () {};
return Select2;//最后生成了select2

下面来细看整个生成过程:

 if ($element.data('select2') != null) {
      $element.data('select2').destroy();
    }

    this.$element = $element;

    this.id = this._generateId($element);

当我们定义的select控件元素属性中定义了data-select2,那么就销毁已生成的插件。

Select2.prototype._generateId = function ($element) {
    var id = '';

    if ($element.attr('id') != null) {
      id = $element.attr('id');
    } else if ($element.attr('name') != null) {
      id = $element.attr('name') + '-' + Utils.generateChars(2);
    } else {
      id = Utils.generateChars(4);
    }

    id = id.replace(/(:|\.|\[|\]|,)/g, '');
    id = 'select2-' + id;

    return id;
  };

这里this.id生成由'select2-'id拼接的标识。接下来可以看到:

options = options || {};

    this.options = new Options(options, $element);

这里初始化了options的信息,new了一下,看一下options这个依赖模块的:

define([
  'require',
  'jquery',
  './defaults',
  './utils'
], function (require, $, Defaults, Utils) {
  function Options (options, $element) {}
  Options.prototype.fromElement = function ($e) {};
  Options.prototype.get = function (key) {};
  Options.prototype.set = function (key, val) {};
return Options;
}

上面采用了同样的注入方式。这里主要看defaultsuntils模块。那么先看options的初始化吧:(继续copy代码^_^~)

    function Options (options, $element) {  
        this.options = options;  

        if ($element != null) {  
          this.fromElement($element);  
        }  

        this.options = Defaults.apply(this.options);  

        if ($element && $element.is('input')) {  
          var InputCompat = require(this.get('amdBase') + 'compat/inputData');  

          this.options.dataAdapter = Utils.Decorate(  
            this.options.dataAdapter,  
            InputCompat  
          );  
        }  
      }  

我们直接跳到this.options = Defaults.apply(this.options);于是我们就看到了select2默认的参数,依赖模块defaults:

  Defaults.prototype.apply = function (options) {
    options = $.extend(true, {}, this.defaults, options);

    if (options.dataAdapter == null) {
      if (options.ajax != null) {
        options.dataAdapter = AjaxData;
      } else if (options.data != null) {
        options.dataAdapter = ArrayData;
      } else {
        options.dataAdapter = SelectData;
      }
//.....
return options;
  };

这里把所有的依赖的模块以define的方式注入到defaultsoptions

define([
  'jquery',
  'require',

  './results',

  './selection/single',
  './selection/multiple',
  './selection/placeholder',
  './selection/allowClear',
  './selection/search',
  './selection/eventRelay',

  './utils',
  './translation',
  './diacritics',

  './data/select',
  './data/array',
  './data/ajax',
  './data/tags',
  './data/tokenizer',
  './data/minimumInputLength',
  './data/maximumInputLength',
  './data/maximumSelectionLength',

  './dropdown',
  './dropdown/search',
  './dropdown/hidePlaceholder',
  './dropdown/infiniteScroll',
  './dropdown/attachBody',
  './dropdown/minimumResultsForSearch',
  './dropdown/selectOnClose',
  './dropdown/closeOnSelect',

  './i18n/en'
]

简单的看下有我们常用的单选下拉,多选下拉,placeholder,ajax...etc...

这样options就初始化完成了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值