jQuery插件制作的实例教程
来源: 阅读:675 次 日期:2016-06-27 16:18:42
温馨提示: 小编为您整理了“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

更多信息请查看网络编程
手机网站地址:jQuery插件制作的实例教程
由于各方面情况的不断调整与变化, 提供的所有考试信息和咨询回复仅供参考,敬请考生以权威部门公布的正式信息和咨询为准!
关于我们 | 联系我们 | 人才招聘 | 网站声明 | 网站帮助 | 非正式的简要咨询 | 简要咨询须知 | 加入群交流 | 手机站点 | 投诉建议
工业和信息化部备案号:滇ICP备2023014141号-1 云南省教育厅备案号:云教ICP备0901021 滇公网安备53010202001879号 人力资源服务许可证:(云)人服证字(2023)第0102001523号
云南网警备案专用图标
联系电话:0871-65317125(9:00—18:00) 获取招聘考试信息及咨询关注公众号:hfpxwx
咨询QQ:526150442(9:00—18:00)版权所有:
云南网警报警专用图标
Baidu
map