网站首页  汉语字词  英语词汇  考试资料  写作素材  旧版资料

请输入您要查询的考试资料:

 

标题 jQuery插件制作的实例教程
内容
    一、jQuery插件的类型
    1. jQuery方法
    很大一部分的jQuery插件都是这种类型,由于此类插件是将对象方法封装起来,在jQuery选择器获取jQuery对象过程中进行操作,从而发挥jQuery强大的选择器优势。
    2. 全局函数法
    可以把自定义的功能函数独立附加到jQuery命名空间下,从而作为jQuery作用域下的一个公共函数使用。
    但全局函数没有被绑定到jQuery对象上,故不能在选择器获取的jQuery对象上调用。需要通过jQuery.fn()或$.fn()方式进行引用。
    3. 选择器法
    如果觉得jQuery提供的选择器不够用或不方便的话,可以考虑自定义选择器。
    二、jQuery插件的机制
    1.   jQuery.extend()方法
    这种方法能够创建全局函数或选择器。
    所谓全局函数,就是jQuery对象的方法,实际上就是位于jQuery命名空间内部的函数,有人把这类函数称为实用工具函数,这些函数都有一个共同特征,就是不直接操作DOM元素,而是操作Javascript的非元素对象,或者执行其他非对象的特定操作,如jQuery的each()函数和noConflict()函数。
    例如,在jQuery命名空间上创建两个公共函数:
    jQuery.extend({ 
    min : function(a,b){ 
    return a<b?a:b; 
    }, 
    max : function(a,b){ 
    return a<b?b:a; 
    } 
    }) 
    $(function(){ 
    $("input").click(function(){ 
    var a = prompt("请输入一个数:"); 
    var b = prompt("再输入一个数:"); 
    var c = jQuery.min(a,b); 
    var d = jQuery.max(a,b); 
    alert("最大值是:" + d + "\n最小值是:" + c); 
    }); 
    }) 
    <input type="button" value="jQuery扩展测试" />
    jQuery.extend({ 
    min : function(a,b){ 
    return a<b?a:b; 
    }, 
    max : function(a,b){ 
    return a<b?b:a; 
    } 
    }) 
    $(function(){ 
    $("input").click(function(){ 
    var a = prompt("请输入一个数:"); 
    var b = prompt("再输入一个数:"); 
    var c = jQuery.min(a,b); 
    var d = jQuery.max(a,b); 
    alert("最大值是:" + d + "\n最小值是:" + c); 
    }); 
    }) 
    <input type="button" value="jQuery扩展测试" />
    jQuery.extend()方法除了可以创建插件外,还可以用来扩展jQuery对象。
    例如,调用jQuery.extend()方法把对象a和对象b合并为一个新的对象,并返回合并对象将其赋值给变量c:
    var a = {name : "aaa",pass : 777}; 
    var b = {name : "bbb",pass : 888,age : 9}; 
    var c = jQuery.extend(a,b); 
    $(function(){ 
    for(var name in c){ 
    $("div").html($("div").html() + "<br />"+ name + ":" + c[name]); 
    } 
    })
    如果要向jQuery命名空间上添加一个函数,只需要将这个新函数制定为jQuery对象的一个属性即可。其中jQuery对象名也可以简写为$,jQuery.smalluv==$.smalluv。
    例如,创建jQuery全局函数:
    jQuery.smalluv = { 
    min : function(a,b){ 
    return a<b?a:b; 
    }, 
    max : function(a,b){ 
    return a<b?b:a; 
    } 
    } 
    $(function(){ 
    $("input").click(function(){ 
    var a = prompt("请输入一个数:"); 
    var b = prompt("再输入一个数:"); 
    var c = jQuery.smalluv.min(a,b); 
    var d = jQuery.smalluv.max(a,b); 
    alert("最大值是:" + d + "\n最小值是:" + c); 
    }); 
    })
    2. jQuery.fn.extend()方法
    这种方法能够创建jQuery对象方法。
    举一个最简单的jQuery对象方法例子:
    jQuery.fn.test = function(){ 
    alert("jQuery对象方法"); 
    } 
    $(function(){ 
    $("div").click(function(){ 
    $(this).test(); 
    }); 
    })
    三、初步总结
    在jQuery匿名函数中,采用jQuery.extend();方法创建jQuery插件
    在jQuery匿名函数中,采用对象.属性=函数的方式创建jQuery插件
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>最简单的jquery插件</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script type="text/javascript" src="../res/jquery/jquery-1.4.4.min.js"></script>
        <script type="text/javascript">
          (function($) {
            jQuery.extend({//写法1
              a: function(h){
                $("#ad").html(h);
              },
              b:function(h){
                alert(h);
              }
            })
          })(jQuery);
          (function($) {//写法2
            jQuery.a=function(h){
              $("#ad").html(h);
            }
            jQuery.b=function(h){
              alert(h);
            }
          })(jQuery);
          $(document).ready(function(){
            $.a("abc");
            $.b("xyz");
          });
        </script>
      </head>
      <body>
        <h3>最简单的jQuery插件</h3>
        <div id="ad"></div>
      </body>
    </html>
    四、编写实例
    写法一
    插件主体:
    (function($, window){
      // 初始态定义
      var _oDialogCollections = {};
      // 插件定义
      $.fn.MNDialog = function (_aoConfig) {
        // 默认参数,可被重写
        var defaults = {
          // string
          sId : "",
          // num
          nWidth : 400,
          // bollean
          bDisplayHeader : true,
          // object
          oContentHtml : "",
          // function
          fCloseCallback : null
        };
        var _oSelf = this,
          $this = $(this);
        // 插件配置
        this.oConfig = $.extend(defaults, _aoConfig);
        // 初始化函数
        var _init = function () {
          if (_oDialogCollections) {
            // 对于已初始化的处理
            // 如果此时已经存在弹框,则remove掉再添加新的弹框
          }
          // 初始化弹出框数据
          _initData();
          // 事件绑定
          _loadEvent();
          // 加载内容
          _loadContent();      
        }
        // 私有函数
        var _initData = function () {};
        var _loadEvent = function () {};
        var _loadContent = function () {
          // 内容(分字符和函数两种,字符为静态模板,函数为异步请求后组装的模板,会延迟,所以特殊处理)
          if($.isFunction(_oSelf.oConfig.oContentHtml)) {
            _oSelf.oConfig.oContentHtml.call(_oSelf, function(oCallbackHtml) {
              // 便于传带参函数进来并且执行
              _oSelf.html(oCallbackHtml);
              // 有回调函数则执行
              _oSelf.oConfig.fLoadedCallback && _oSelf.oConfig.fLoadedCallback.call(_oSelf, _oSelf._oContainer$);
            });
          } else if ($.type(_oSelf.oConfig.oContentHtml) === "string") {
            _oSelf.html(_oSelf.oConfig.oContentHtml);
            _oSelf.oConfig.fLoadedCallback && _oSelf.oConfig.fLoadedCallback.call(_oSelf, _oSelf._oContainer$);
          } else {
            console.log("弹出框的内容格式不对,应为function或者string。");
          }
        };
        // 内部使用参数
        var _oEventAlias = {
          click     : 'D_ck',
          dblclick   : 'D_dbl'
        };
        // 提供外部函数
        this.close = function () {
          _close();
        }    
        // 启动插件
        _init();
        // 链式调用
        return this;    
      };
      // 插件结束
    })(jQuery, window);
    调用
    var MNDialog = $("#header").MNDialog({
      sId : "#footer",    //覆盖默认值
      fCloseCallback : dialog,//回调函数
      oContentHtml : function(_aoCallback){
          _aoCallback(_oEditGrpDlgView.el);
        }
      }
    });
    // 调用提供的函数
    MNDialog.close;
    function dialog(){
    }
    点评
    1. 自调用匿名函数
    (function($, window) {
     // jquery code
    })(jQuery, window);
    用处:通过定义一个匿名函数,创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏全局的命名空间。这点非常有用也是一个JS框架必须支持的功能,jQuery被应用在成千上万的JavaScript程序中,必须确保jQuery创建的变量不能和导入他的程序所使用的变量发生冲突。
    2. 匿名函数为什么要传入window
    通过传入window变量,使得window由全局变量变为局部变量,当在jQuery代码块中访问window时,不需要将作用域链回退到顶层作用域,这样可以更快的访问window;这还不是关键所在,更重要的是,将window作为参数传入,可以在压缩代码时进行优化,看看jquery.min.js:
    (function(a,b){})(jQuery, window); // jQuery被优化为a, window 被优化为 b
    3. 全局变量this定义
    var _oSelf = this,
    $this = $(this);
    使得在插件的函数内可以使用指向插件的this
    4. 插件配置
    this.oConfig = $.extend(defaults, _aoConfig);
    设置默认参数,同时也可以再插件定义时传入参数覆盖默认值
    5. 初始化函数
    一般的插件会有init初始化函数并在插件的尾部初始化
    6. 私有函数、公有函数
    私有函数:插件内使用,函数名使用”_”作为前缀标识
    共有函数:可在插件外使用,函数名使用”this.”作为前缀标识,作为插件的一个方法供外部使用
    7. return this
    最后返回jQuery对象,便于jQuery的链式操作
    写法二
    主体结构
    (function($){
      $.fn.addrInput = function(_aoOptions){
        var _oSelf = this;
        _oSelf.sVersion = 'version-1.0.0';
        _oSelf.oConfig = {
          nInputLimitNum : 9
        };
        // 插件配置
        $.extend(_oSelf.oConfig, _aoOptions);
        // 调用这个对象的方法,传递this
        $.fn.addrInput._initUI.call(_oSelf, event);
        $.fn.addrInput._initEvents.call(_oSelf);
        // 提供外部函数
        this.close = function () {
          _close();
        }
        //返回jQuery对象,便于Jquery的链式操作  
        return _oSelf;          
      }
      $.fn.addrInput._initUI = function(event){
        var _oSelf = this,
          _oTarget = $(event.currentTarget);
      }
      $.fn.addrInput._initEvents = function(){}
    })(window.jQuery);
    点评
    1. 美观
    插件的方法写在外部,并通过在插件主体传递this的方式调用
    2. 定义插件版本号
    不过在这里还是没有用到
    3. 关于call
    这里的第一个参数为传递this,后面的均为参数
    语法:
    call([thisObj[,arg1[, arg2[, [,.argN]]]]])
    定义:调用一个对象的一个方法,以另一个对象替换当前对象。
    说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
    4. 关于”this”
    在插件的方法中,可能有用到指向插件的this、和指向事件触发的this,所以事件触发的this用event来获取:event.cuerrntTarget
    event.currentTarget:指向事件所绑定的元素,按照事件冒泡的方式,向上找到元素
    event.target:始终指向事件发生时的元素
    如:
    html代码
    <div id="wrapper"> 
      <a href="#" id="inner">click here!</a> 
    </div>
     js代码
    $('#wrapper').click(function(e) { 
      console.log('#wrapper'); 
      console.log(e.currentTarget); 
      console.log(e.target); 
    }); 
    $('#inner').click(function(e) { 
      console.log('#inner'); 
      console.log(e.currentTarget); 
      console.log(e.target); 
    });
    结果输出
    #inner
    <a href="#" id="inner">click here!</a>
    <a href="#" id="inner">click here!</a>
    #wrapper
    <div id="wrapper"><a href="#" id="inner">click here!</a></div>
    <a href="#" id="inner">click here!</a>
    写法三(原生写法)
    主体结构
    var MemberCard = function(_aoOption){
      // 配置(默认是从外面传进来)
      _aoOption || (_aoOption = {}) ;
      // 初始化函数
      _init(this);
    }
    var _init = function(_aoSelf) {
      // 函数执行
      _initData(_aoSelf);
      // 调用对象的私有方法
      _aoSelf._timedHide();
    }
    var _initData = function ( _aoSelf ) {}
    // 私有方法
    MemberCard.prototype._timedHide = function(_aoOptions) {
      var _oSelf = this;
      clearTimeout(this.iHideTimer);  
      // 使用underscore.js的extend方法来实现属性覆盖
      var oDefault = extend( { nHideTime: 300 }, _aoOptions );
      _oSelf.iHideTimer = setTimeout( function(){
        // 调用对象的共有方法
        _oSelf.hide();
      }, oDefault.nHideTime);    
    }
    // 公有方法
    MemberCard.prototype.hide = function(_aoOptions) {}
    使用
    var oColleagueCard = new MemberCard({ nHideTime: 200 });
    oColleagueCard.hide();
    点评:
    1. 关于属性覆盖(对象深拷贝)
    原生函数实现方法
    function getType(o){
      return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase();
    }
    function extend(destination,source){
      for(var p in source){
        if(getType(source[p])=="array"||getType(source[p])=="object"){
          destination[p]=getType(source[p])=="array"?[]:{};
          arguments.callee(destination[p],source[p]);
        }else{
          destination[p]=source[p];
        }
      }
    }
    demo:
    var test={a:"ss",b:[1,2,3],c:{d:"css",e:"cdd"}};
    var test1={};
    extend(test1,test);
    test1.b[0]="change"; //改变test1的b属性对象的第0个数组元素
    alert(test.b[0]); //不影响test,返回1
    alert(test1.b[0]); //返回change
    基于jQuery的实现方法:
    jQuery.extend([deep], target, object1, [objectN]);
    用一个或多个其他对象来扩展一个对象,返回被扩展的对象。
    如果不指定target,则给jQuery命名空间本身进行扩展。这有助于插件作者为jQuery增加新方法。 如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 未定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制。
    demo:
    var options = {id: "nav", class: "header"}
    var config = $.extend({id: "navi"}, options); //config={id: "nav", class: "header"}
     2. 关于this
    这个对象的所有方法的this都指向这个对象,所以就不需要重新指定
    写法四
    主体结构
    function EditorUtil() {
      this._editorContent = $( '#editor_content' );
      this._picBtn = $( '#project_pic' );
      this.ieBookmark = null;
    }
    EditorUtil.prototype = {
      consturctor: EditorUtil,
      noteBookmark: function() {
      },
      htmlReplace: function( text ) {
        if( typeof text === 'string' ) {
          return text.replace( /[<>"&]/g, function( match, pos, originalText ) {
            switch( match ) {
              case '<':
                return '<';
              case '>':
                return '>';
              case '&':
                return '&';
              case '"':
                return '"';
            }
          });
        }
        return '';
      },
      init: function() {
        this._memBtn.bind( 'click', function( event ) {
          $(".error_content").hide();
          return false;
        });
      }
    };
    // 初始化富文本编辑器
    var editor = new EditorUtil();
    editor.init();
    总结
    写法四和写法三其实都差不多,但是你们有没有看出其中的不一样呢?
    两种都是利用原型链给对象添加方法:
    写法三:
    MemberCard.prototype._timedHide
    MemberCard.prototype.hide
    写法四:
    EditorUtil.prototype = {
      consturctor: EditorUtil,
      noteBookmark: function(){},  
      htmlReplace: function(){}
    }
    细看写法四利用“对象直接量”的写法给EditorUtil对象添加方法,和写法三的区别在于写法四这样写会造成consturctor属性的改变
    constructor属性:始终指向创建当前对象的构造函数
    每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数。如下例所示:
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype.getName = function() { 
      return this.name; 
    }; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Person); // true 
    console.log(Person.prototype.constructor === Person); // true 
    // 将上两行代码合并就得到如下结果 
    console.log(p.constructor.prototype.constructor === Person); // true
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype.getName = function() { 
      return this.name; 
    }; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Person); // true 
    console.log(Person.prototype.constructor === Person); // true 
    // 将上两行代码合并就得到如下结果 
    console.log(p.constructor.prototype.constructor === Person); // true
    当时当我们重新定义函数的prototype时(注意:和上例的区别,这里不是修改而是覆盖),constructor属性的行为就有点奇怪了,如下示例:
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype = { 
      getName: function() { 
        return this.name; 
      } 
    }; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Person); // false 
    console.log(Person.prototype.constructor === Person); // false 
    console.log(p.constructor.prototype.constructor === Person); // false
    为什么呢?
    原来是因为覆盖Person.prototype时,等价于进行如下代码操作:
    Person.prototype = new Object({ 
      getName: function() { 
        return this.name; 
      } 
    });
    Person.prototype = new Object({ 
      getName: function() { 
        return this.name; 
      } 
    });
    而constructor属性始终指向创建自身的构造函数,所以此时Person.prototype.constructor === Object,即是:
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype = { 
      getName: function() { 
        return this.name; 
      } 
    }; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Object); // true 
    console.log(Person.prototype.constructor === Object); // true 
    console.log(p.constructor.prototype.constructor === Object); // true
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype = { 
      getName: function() { 
        return this.name; 
      } 
    }; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Object); // true 
    console.log(Person.prototype.constructor === Object); // true 
    console.log(p.constructor.prototype.constructor === Object); // true
    怎么修正这种问题呢?方法也很简单,重新覆盖Person.prototype.constructor即可:
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype = new Object({ 
      getName: function() { 
        return this.name; 
      } 
    }); 
    Person.prototype.constructor = Person; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Person); // true 
    console.log(Person.prototype.constructor === Person); // true 
    console.log(p.constructor.prototype.constructor === Person); // true
    function Person(name) { 
      this.name = name; 
    }; 
    Person.prototype = new Object({ 
      getName: function() { 
        return this.name; 
      } 
    }); 
    Person.prototype.constructor = Person; 
    var p = new Person("ZhangSan"); 
    console.log(p.constructor === Person); // true 
    console.log(Person.prototype.constructor === Person); // true 
    console.log(p.constructor.prototype.constructor === Person); // true
随便看

 

在线学习网考试资料包含高考、自考、专升本考试、人事考试、公务员考试、大学生村官考试、特岗教师招聘考试、事业单位招聘考试、企业人才招聘、银行招聘、教师招聘、农村信用社招聘、各类资格证书考试等各类考试资料。

 

Copyright © 2002-2024 cuapp.net All Rights Reserved
更新时间:2025/5/15 16:07:42