zoukankan      html  css  js  c++  java
  • jquery插件模版

    自己写jquery插件之模版插件高级篇(一)

    需求场景

    最近项目改版中,发现很多地方有这样一个操作(见下图gif动画演示),很多地方都有用到。这里不讨论它的用户体验怎么样。

    仅仅是从复用的角度,如果每个页面都去写text和select元素,两个button按钮,增加add和delete对应的js函数,无疑大大增加了工作量和维护成本。

    select有预设值的情况:

    下面就开始动手把这4个html元素做成一个JQuery插件。

    jquery插件结构

    如果你是零基础,请参考Jquery官网对jquery plugin的介绍:http://learn.jquery.com/plugins/

    整个插件做好后是一个js文件,我们首先来看下它的整体结构,如下图:

    调用时的代码(无参):

    $(".demo1").dlpcustomSelect();

    调用时的代码(有参):

    $(".demo1").dlpcustomSelect({
          addButtonText:'Add',
          delButtonText:'>>'
    });

    前台HTML:

    <select class="demo1"></select>

    这样就把插件定义的html元素全部渲染出来了,插件自带了相关js函数和功能。代码维护起来非常方便。

    下面我们开始这个Jquery插件的制作过程:

    一. 定义插件结构,插件名称,默认值和构造函数

    1.插件结构,名称,默认值

    新建dlpcustomselect.js文件后,我们首先书写这样的代码:

    ;(function ($, window, document, undefined) {
      //Author:HANGWEI
      //Create the defaults once
      var pluginName = 'dlpcustomSelect',
        defaults = {
          addButtonEnabled : true,
          addButtonText: 'Add',
          delButtonText:'Delete'
        };
    //... other code ...
    
    // A really lightweight plugin wrapper around the constructor,
      // preventing against multiple instantiations
      $.fn[ pluginName ] = function (options) {
        var args = arguments;
    
        // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
        if (options === undefined || typeof options === 'object') {
          return this.each(function () {
            // If this is not a select
            if (!$(this).is('select')) {
              $(this).find('select').each(function(index, item) {
                // For each nested select, instantiate the dlp custom select
                $(item).dlpcustomSelect(options);//注意此处的插件名称
              });
            } else if (!$.data(this, 'plugin_' + pluginName)) {
              // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet
    
              // if it has no instance, create a new one, pass options to our plugin constructor,
              // and store the plugin instance in the elements jQuery data object.
              $.data(this, 'plugin_' + pluginName, new DlpCustomSelect(this, options));//注意此处插件的构造函数
            }
          });
          // If the first parameter is a string and it doesn't start with an underscore or "contains" the `init`-function,
          // treat this as a call to a public method.
        } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
    
          // Cache the method call to make it possible to return a value
          var returns;
    
          this.each(function () {
            var instance = $.data(this, 'plugin_' + pluginName);
            // Tests that there's already a plugin-instance and checks that the requested public method exists
            if (instance instanceof DlpCustomSelect && typeof instance[options] === 'function') {//注意此处插件构造函数名
              // Call the method of our plugin instance, and pass it the supplied arguments.
              returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
            }
          });
    
          // If the earlier cached method gives a value back return the value,
          // otherwise return this to preserve chainability.
          return returns !== undefined ? returns : this;
        }
    
      };
    
    })(jQuery, window, document);

     在上述代码中,pluginName是插件名称,defaults规定了插件的三个参数及其默认值;

     $.fn[pluginName]=function(options){};函数的功能,如代码注释所说,阻止多个插件实例被创建。

     ;(function ($, window, document, undefined) {  这句代码的详细解释请参考 这里

    2. 构造函数

      // The actual plugin constructor
      function DlpCustomSelect(element, options) {
        this.element = $(element);
        // jQuery has an extend method which merges the contents of two or
        // more objects, storing the result in the first object. The first object
        // is generally empty as we don't want to alter the default options for
        // future instances of the plugin
        this.settings = $.extend({}, defaults, options);
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
      }

    构造函数用于初始化和参数定义,如无特殊需求, 可参考上述写法来定义。

    二. 编写插件核心部分代码

    下面我们开始章节一代码结构中: other code 的部分

    1. 构造函数名.prototype={...};

      1 DlpCustomSelect.prototype = {
      2     init: function () {
      3       // Add the custom HTML template
      4       this.container = $('' +
      5       '<div class="dlpcustomselect-container">' +
      6         '<table class="box1">' +
      7         ' <tr>' +
      8         '   <td><input class="waitAddValue" type="text" size="48" /></td>' +
      9         '   <td><input class="btn-pull-buttom" type="button" /></td>' +
     10         ' </tr>' +
     11         ' <tr>' +
     12         '   <td><select style=" 265px;height: 100px" multiple="multiple"></select></td>' +
     13         '   <td><input class="btn-delete-buttom" type="button" /></td>' +
     14         ' </tr>' +
     15         '</table>'+
     16       '</div>')
     17         .insertBefore(this.element);
     18 
     19       // Cache the inner elements
     20       this.elements = {
     21         originalSelect: this.element,
     22         box1: $('.box1', this.container),
     23         filterInput1: $('.box1 .waitAddValue', this.container),
     24         select1: $('.box1 select', this.container),
     25         addButton: $('.box1 .btn-pull-buttom', this.container),
     26         deleteButton: $('.box1 .btn-delete-buttom', this.container)
     27       };
     28 
     29       // Set select IDs
     30       this.originalSelectName = this.element.attr('name') || '';
     31       var select1Id = 'dlpcustomselect-list_' + this.originalSelectName;
     32       this.elements.select1.attr('id', select1Id);
     33 
     34       // Apply all settings
     35       this.setAddButtonEnabled(this.settings.addButtonEnabled);
     36       this.setAddButtonText(this.settings.addButtonText);
     37       this.setDelButtonText(this.settings.delButtonText);
     38 
     39       //updateSelectionStates(this);
     40       // Hide the original select
     41       this.element.hide();
     42 
     43       bindEvents(this);
     44       refreshSelects(this);
     45 
     46       return this.element;
     47     },
     48     setAddButtonEnabled: function(value, refresh) {
     49       this.settings.addButtonEnabled = value;
     50       if (value) {
     51         this.container.find('.btn-pull-buttom').removeAttr("disabled");
     52       } else {
     53         this.container.find('.btn-pull-buttom').attr("disabled","disabled");
     54       }
     55       if (refresh) {
     56         //refreshSelects(this);
     57       }
     58       return this.element;
     59     },
     60     setAddButtonText: function(value, refresh) {
     61       this.settings.addButtonText = value;
     62       if (value) {
     63         this.elements.addButton.show().val(value);
     64         //if upper code type doesn't work,use this code.
     65         //this.container.find('.btn-pull-buttom').show().val(value);
     66       } else {
     67         this.elements.addButton.hide().val(value);
     68         //if upper code type doesn't work,use this code.
     69         //this.container.find('.btn-pull-buttom').hide().val(value);
     70       }
     71       if (refresh) {
     72         //refreshSelects(this);
     73       }
     74       return this.element;
     75     },
     76     setDelButtonText: function(value, refresh) {
     77       this.settings.delButtonText = value;
     78       if (value) {
     79         this.elements.deleteButton.show().val(value);
     80       } else {
     81         this.elements.deleteButton.hide().val(value);
     82       }
     83       if (refresh) {
     84         //refreshSelects(this);
     85       }
     86       return this.element;
     87     },
     88     getCustomData: function(){
     89       var terms = new Array();
     90       this.container.find('.box1 select option').each(function(index, item) {
     91         terms.push(item['value']);
     92       });
     93       return terms;
     94     },
     95     getContainer: function() {
     96       return this.container;
     97     },
     98     destroy: function() {
     99       this.container.remove();
    100       this.element.show();
    101       $.data(this, 'plugin_' + pluginName, null);
    102       return this.element;
    103     }
    104   };
    View Code

    init:function(){...}  需要实现的init函数,这里我们用来创建html模板、应用所有的设置、调用绑定事件。

    方法 refreshSelects(this)用来将前台select中的元素(如果有的话)copy到插件中。

    方法 getCustomData用来返回插件的值

    这里的设计思路是:隐藏你在前台写的select元素,返回插件模板中的自定义html串。另外,如果前台select中有option元素,则同步copy到插件中。

    三. 绑定插件按钮事件和书写自定义功能函数

    //bind events for button
      function bindEvents(dlpCustomSelect) {
        dlpCustomSelect.elements.addButton.on('click', function() {
          addOption(dlpCustomSelect);
        });
        dlpCustomSelect.elements.deleteButton.on('click', function() {
          deleteOption(dlpCustomSelect);
        });
          //backup method.
          /*
          $(document).on('click', '.box1 .btn-pull-buttom', function() {
              addOption(dlpCustomSelect);
          });
          */
      }

    如以上代码所示,绑定插件的两个按钮的事件。其中addOption和deleteOption函数具体实现这里不再详细阐述。 

    根据项目实际需要,增加自定义绑定事件和函数。

    四. 完成并测试

    调用插件:

    $(".demo1").dlpcustomSelect({
                    addButtonText:'Add',
                    delButtonText:'>>'
                });

    不更改参数值,直接调用(使用默认参数值):

    $(".demo2").dlpcustomSelect();

    获取插件中的值:$(".demo1").dlpcustomSelect('getCustomData')

    demo下载

    总结

    本插件的实现大量参考了国外jquery插件制作的通用做法。希望本篇文章能起到抛砖引玉的作用,能引导开发人员自己动手写jquery插件。

    本来想挂在github上,但鉴于这个插件的功能很少,就不费周章了。需要的直接在本篇文章下载吧。

    另外本人水平有限,如有错误之处还请各位批评指正。

    希望本文对你有帮助。

  • 相关阅读:
    js计算器
    还差得远
    首个项目结束
    Web前端开发规范文档你需要知道的事
    CSS需要经过多次练习和积累才能掌握
    在Javascript中闭包(Closure)
    Web前端和网站美工
    IE中的条件注释
    计算机类期刊投稿
    忙就一个字
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5068087.html
Copyright © 2011-2022 走看看