silvermyth

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            1 隨筆 :: 12 文章 :: 1 評論 :: 0 Trackbacks
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿

          文章分類

          文章檔案

          搜索

          最新評論

               先講一下背景,最近發現項目中有些js文件的規模越來越大,接近2000行,開始出現維護困難的苗頭;剛好實現的一個功能需要用到tree插件,在網上搜到一個bootstrap treeview插件可以用,但該插件無法支持懶加載和動態添加功能,網上現有的擴展方案都無法完全滿足我的要求?;艘恍r間看了bootstrap treeview的代碼和Jquery插件的編寫方法,對其進行了擴展并在項目中實現了一個簡單的Select插件;另外計劃把項目中以前組件化的自定義UI控件也全部用Jquery插件實現,以便復用并且清除冗余代碼,這一過程我會陸續發布出來,本篇主要以我的select插件為例講述如何才能編寫一個Jquery插件:
              要想編寫一個Jquery插件,首先必須對Jquery有所了解,尤其是以下幾個知識點:
          •     知道(function($){...})(jQuery)是什么意思
            (function($){...})(jQuery)定義了一個函數,并且以jQuery為參數進行了調用,一般情況下,這是實現jQuery插件的標準姿勢,對這個有興趣的同學可以繼續深入研究。
          •     $.proxy(fun, context)
            該方法返回一個fun函數的代理,返回的代理函數功能和fun相同,不同的是返回函數使用context參數作為調用上下文。這段話有點繞口,不明白的同學請參考:
            http://www.cnblogs.com/hongchenok/p/3919497.html
          •     $.each(arr, function(){...})
            該方法在每個arr中的元素上執行callback方法,存在很多變體。詳細請參見http://www.jb51.net/article/24581.htm
          •     $.extend(deep, obj, obj1, ..)
            Jquery提供的用來擴展一個對象的方法,即將對象obj1合并到對象obj,一般被用來向jQuery對象中添加方法。詳細請參考http://www.cnblogs.com/tianguook/p/4084061.html
          •     $.data(dom, data-name, data-value)
            Jquery提供的用來綁定對象到dom對象中的方法,如果沒有定義data-value參數,是讀取data-name的值;如果定義了data-value則是設置data-name的值。
                有了以上知識,我們來實現一個Select的Jquery插件,可以方便的創建、添加選項、刪除選項等等。代碼如下:
              /**
           * Created by gavinli on 17-3-30.
           
          */
          ;(function ($) {
              'use strict';

              var pluginName = 'myList';

              var _default = {};

              _default.settings = {};

              var MyList = function (element, options) {
                  this.$element = $(element);
                  this.init(options);
                  return {
                      init: $.proxy(this.init, this),
                      add: $.proxy(this.add, this),
                      remove: $.proxy(this.remove, this),
                      list: $.proxy(this.list, this),
                      clear: $.proxy(this.clear, this),
                      getSelected: $.proxy(this.getSelected, this)
                  }
              };

              MyList.prototype.init = function (options) {
                  this.items = [];

                  if (options.data) {
                      if (typeof options.data === 'string') {
                          options.data = $.parseJSON(options.data);
                      }
                      this.items = $.extend(true, [], options.data);
                      delete options.data;
                  }
                  this.options = $.extend({}, _default.settings, options);
                  this.render();
                  this.subscribeEvents();
              };

              MyList.prototype.subscribeEvents = function () {
                  //TODO:
              };

              MyList.prototype.add = function (items) {
                  if (!(items instanceof Array)) {
                      items = [items];
                  }
                  var _this = this;
                  $.each(items, function (i, value) {
                      _this.items.push(value);
                  });
                  this.filterDup();
                  this.render();
              }

              //Remove all duplicated items
              MyList.prototype.filterDup = function () {
                  var _this = this;
                  var values = {}
                  $.each(_this.items, function (i, value) {
                      if (values[value]) {
                          _this.items[i] = null;
                      } else {
                          values[value] = true;
                      }
                  });
              }

              MyList.prototype.remove = function (items) {
                  var _this = this;
                  var toBeRemoved = {};
                  $.each(items, function (i, value) {
                      toBeRemoved[value] = true;
                  });
                  $.each(_this.items, function (i, value) {
                      if (toBeRemoved[value] == true) {
                          _this.items[i] = null;
                      }
                  });
                  this.render();
              }

              MyList.prototype.getSelected = function () {
                  return this.$wrapper.val();
              }

              MyList.prototype.list = function (item) {
                  var result = [];
                  $.each(this.items, function (i, value) {
                      if (value) {
                          result.push(value);
                      }
                  });
                  return result;
              }

              //Clear all items
              MyList.prototype.clear = function () {
                  delete this.items;
                  this.items = [];
                  this.render();
              }

              MyList.prototype.render = function () {
                  if (!this.initialized) {
                      this.$wrapper = $(this.template.list);
                      this.initialized = true;
                  }
                  //Append select element to $element
                  this.$element.empty().append(this.$wrapper.empty());

                  //Build select options
                  this.buildList(this.items);
              }

              MyList.prototype.buildList = function (items) {
                  var _this = this;
                  $.each(items, function (i, value) {
                      if (value) {
                          var option = $(_this.template.item);
                          option.append(value);
                          _this.$wrapper.append(option);
                      }
                  });
              }

              MyList.prototype.template = {
                  list: '<select multiple class="form-control"></select>',
                  item: '<option></option>'
              };

              $.fn[pluginName] = function (options, args) {
                  var result;
                  this.each(function () {
                      var _this = $.data(this, pluginName);
                      if (typeof options === 'string') {
                          if (!_this) {
                              //logError('Not initialized, can not call method : ' + options);
                          }
                          else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {
                              //logError('No such method : ' + options);
                          }
                          else {
                              if (!(args instanceof Array)) {
                                  args = [args];
                              }
                              result = _this[options].apply(_this, args);
                          }
                      }
                      else if (typeof options === 'boolean') {
                          result = _this;
                      }
                      else {
                          $.data(this, pluginName, new MyList(this, $.extend(true, {}, options)));
                      }
                  });
                  return result || this;
              };

          })(jQuery);
              下面針對其中的關鍵方法進行分析講解:
              MyList函數:MyList對象的construnctor方法,接受options參數(options參數包含所有options的數組)
              MyList.prototype.init:根據options的data構建并渲染Select控件
              MyList.prototype.add:添加option到Select中并渲染,其它remove,list,getSelected方法大家自行研究
              上面代碼中,最核心的部分在于如何將MyList對象和Dom元素結合、并且擴展到Jquery中,具體參考如下注釋代碼:
              ////擴展jQuery的prototype對象,這里的plugName等于myList,相當于給jQuery對象添加了一個"myList"方法
              $.fn[pluginName] = function (options, args) { 
                  var result;
                  ////這里的this是一個jQuery對象
                  this.each(function () {    
                      //下面的this不是jQuery對象,而是jQuery對象中的Dom對象
                      //從Dom對象中獲取"data-myList"屬性綁定的對象
                      var _this = $.data(this, pluginName);
                      //options是方法名,例如$('#list1').MyList('add',[]),這里的options等于'add'
                      if (typeof options === 'string') {
                          if (!_this) {
                              //logError('Not initialized, can not call method : ' + options);
                          }
                          else if (!$.isFunction(_this[options]) || options.charAt(0) === '_') {
                              //logError('No such method : ' + options);
                          }
                          else {
                              if (!(args instanceof Array)) {
                                  args = [args];
                              }
                              //調用MyList對象的方法
                              result = _this[options].apply(_this, args);
                          }
                      }
                      else if (typeof options === 'boolean') {
                          result = _this;
                      }
                      else {
                          //創建MyList對象并綁定到Dom對象的data-myList屬性
                          $.data(this, pluginName, new MyList(this, $.extend(true, {}, options)));
                      }
                  });
                  return result || this;
              };
             如何使用該插件的方法如下所示:
              首先在html中定義一個<div id="list1"></div>,然后這樣使用它:
              //創建一個Select包含三個options
          $('#list1').MyList(['Tom','Mary','Alice']);
          //添加新的option
          $('#list1').MyList('add', [['James','Richard']]);
          //刪除option
          $('#list1').MyList('remove', [['Alice']]);
              最后我們可以在以上例子中發現創建jQuery插件的總體思路:
          •     自定義對象,對象中包含數據和jQuery對象本身
          •     定義對象的方法,并且根據對象中數據的變化渲染Dom對象(通過jQuery對象獲得Dom對象)
          •     將該自定義對象方法擴展到jQuery原型對象中
          •     創建自定義對象,并綁定到jQuery中Dom對象的data屬性
              通過以上實現,我們便可以像使用jQuery對象一樣的方式使用控件,屏蔽對Dom元素的操作,簡單又方便
          posted on 2017-04-05 17:35 Gavin Li 閱讀(132) 評論(0)  編輯  收藏 所屬分類: JavaScript

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 惠水县| 都江堰市| 师宗县| 凤台县| 大洼县| 化州市| 承德县| 寿宁县| 上犹县| 温州市| 天台县| 双辽市| 拜城县| 苏尼特左旗| 师宗县| 林州市| 老河口市| 南澳县| 阆中市| 启东市| 隆林| 金阳县| 金川县| 通许县| 井陉县| 南充市| 永嘉县| 瓦房店市| 蒲江县| 天祝| 崇州市| 永靖县| 逊克县| 乐陵市| 时尚| 文登市| 图片| 昌都县| 英超| 广宗县| 光泽县|