jQuery插件制作的實(shí)例教程
一、jQuery插件的類型
1. jQuery方法
很大一部分的jQuery插件都是這種類型,由于此類插件是將對象方法封裝起來,在jQuery選擇器獲取jQuery對象過程中進(jìn)行操作,從而發(fā)揮jQuery強(qiáng)大的選擇器優(yōu)勢。
2. 全局函數(shù)法
可以把自定義的功能函數(shù)獨(dú)立附加到j(luò)Query命名空間下,從而作為jQuery作用域下的一個公共函數(shù)使用。
但全局函數(shù)沒有被綁定到j(luò)Query對象上,故不能在選擇器獲取的jQuery對象上調(diào)用。需要通過jQuery.fn()或$.fn()方式進(jìn)行引用。
3. 選擇器法
如果覺得jQuery提供的選擇器不夠用或不方便的話,可以考慮自定義選擇器。
二、jQuery插件的機(jī)制
1. jQuery.extend()方法
這種方法能夠創(chuàng)建全局函數(shù)或選擇器。
所謂全局函數(shù),就是jQuery對象的方法,實(shí)際上就是位于jQuery命名空間內(nèi)部的函數(shù),有人把這類函數(shù)稱為實(shí)用工具函數(shù),這些函數(shù)都有一個共同特征,就是不直接操作DOM元素,而是操作Javascript的非元素對象,或者執(zhí)行其他非對象的特定操作,如jQuery的each()函數(shù)和noConflict()函數(shù)。
例如,在jQuery命名空間上創(chuàng)建兩個公共函數(shù):
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("請輸入一個數(shù):"); var b = prompt("再輸入一個數(shù):"); var c = jQuery.min(a,b); var d = jQuery.max(a,b); alert("最大值是:" + d + "\n最小值是:" + c); }); })
<input type="button" value="jQuery擴(kuò)展測試" />
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("請輸入一個數(shù):"); var b = prompt("再輸入一個數(shù):"); var c = jQuery.min(a,b); var d = jQuery.max(a,b); alert("最大值是:" + d + "\n最小值是:" + c); }); })
<input type="button" value="jQuery擴(kuò)展測試" />
jQuery.extend()方法除了可以創(chuàng)建插件外,還可以用來擴(kuò)展jQuery對象。
例如,調(diào)用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命名空間上添加一個函數(shù),只需要將這個新函數(shù)制定為jQuery對象的一個屬性即可。其中jQuery對象名也可以簡寫為$,jQuery.smalluv==$.smalluv。
例如,創(chuàng)建jQuery全局函數(shù):
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("請輸入一個數(shù):"); var b = prompt("再輸入一個數(shù):"); var c = jQuery.smalluv.min(a,b); var d = jQuery.smalluv.max(a,b); alert("最大值是:" + d + "\n最小值是:" + c); }); })
2. jQuery.fn.extend()方法
這種方法能夠創(chuàng)建jQuery對象方法。
舉一個最簡單的jQuery對象方法例子:
jQuery.fn.test = function(){ alert("jQuery對象方法"); } $(function(){ $("div").click(function(){ $(this).test(); }); })
三、初步總結(jié)
在jQuery匿名函數(shù)中,采用jQuery.extend();方法創(chuàng)建jQuery插件
在jQuery匿名函數(shù)中,采用對象.屬性=函數(shù)的方式創(chuàng)建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>
四、編寫實(shí)例
寫法一
插件主體:
(function($, window){ // 初始態(tài)定義 var _oDialogCollections = {}; // 插件定義 $.fn.MNDialog = function (_aoConfig) { // 默認(rèn)參數(shù),可被重寫 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); // 初始化函數(shù) var _init = function () { if (_oDialogCollections) { // 對于已初始化的處理 // 如果此時已經(jīng)存在彈框,則remove掉再添加新的彈框 } // 初始化彈出框數(shù)據(jù) _initData(); // 事件綁定 _loadEvent(); // 加載內(nèi)容 _loadContent(); } // 私有函數(shù) var _initData = function () {}; var _loadEvent = function () {}; var _loadContent = function () { // 內(nèi)容(分字符和函數(shù)兩種,字符為靜態(tài)模板,函數(shù)為異步請求后組裝的模板,會延遲,所以特殊處理) if($.isFunction(_oSelf.oConfig.oContentHtml)) { _oSelf.oConfig.oContentHtml.call(_oSelf, function(oCallbackHtml) { // 便于傳帶參函數(shù)進(jìn)來并且執(zhí)行 _oSelf.html(oCallbackHtml); // 有回調(diào)函數(shù)則執(zhí)行 _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("彈出框的內(nèi)容格式不對,應(yīng)為function或者string。"); } }; // 內(nèi)部使用參數(shù) var _oEventAlias = { click : 'D_ck', dblclick : 'D_dbl' }; // 提供外部函數(shù) this.close = function () { _close(); } // 啟動插件 _init(); // 鏈?zhǔn)秸{(diào)用 return this; }; // 插件結(jié)束 })(jQuery, window);
調(diào)用
var MNDialog = $("#header").MNDialog({ sId : "#footer", //覆蓋默認(rèn)值 fCloseCallback : dialog,//回調(diào)函數(shù) oContentHtml : function(_aoCallback){ _aoCallback(_oEditGrpDlgView.el); } } }); // 調(diào)用提供的函數(shù) MNDialog.close; function dialog(){ }
點(diǎn)評
1. 自調(diào)用匿名函數(shù)
(function($, window) { // jquery code })(jQuery, window);
用處:通過定義一個匿名函數(shù),創(chuàng)建了一個“私有”的命名空間,該命名空間的變量和方法,不會破壞全局的命名空間。這點(diǎn)非常有用也是一個JS框架必須支持的功能,jQuery被應(yīng)用在成千上萬的JavaScript程序中,必須確保jQuery創(chuàng)建的變量不能和導(dǎo)入他的程序所使用的變量發(fā)生沖突。
2. 匿名函數(shù)為什么要傳入window
通過傳入window變量,使得window由全局變量變?yōu)榫植孔兞浚?dāng)在jQuery代碼塊中訪問window時,不需要將作用域鏈回退到頂層作用域,這樣可以更快的訪問window;這還不是關(guān)鍵所在,更重要的是,將window作為參數(shù)傳入,可以在壓縮代碼時進(jìn)行優(yōu)化,看看jquery.min.js:
(function(a,b){})(jQuery, window); // jQuery被優(yōu)化為a, window 被優(yōu)化為 b
3. 全局變量this定義
var _oSelf = this, $this = $(this);
使得在插件的函數(shù)內(nèi)可以使用指向插件的this
4. 插件配置
this.oConfig = $.extend(defaults, _aoConfig);
設(shè)置默認(rèn)參數(shù),同時也可以再插件定義時傳入?yún)?shù)覆蓋默認(rèn)值
5. 初始化函數(shù)
一般的插件會有init初始化函數(shù)并在插件的尾部初始化
6. 私有函數(shù)、公有函數(shù)
私有函數(shù):插件內(nèi)使用,函數(shù)名使用”_”作為前綴標(biāo)識
共有函數(shù):可在插件外使用,函數(shù)名使用”this.”作為前綴標(biāo)識,作為插件的一個方法供外部使用
7. return this
最后返回jQuery對象,便于jQuery的鏈?zhǔn)讲僮?/p>
寫法二
主體結(jié)構(gòu)
(function($){ $.fn.addrInput = function(_aoOptions){ var _oSelf = this; _oSelf.sVersion = 'version-1.0.0'; _oSelf.oConfig = { nInputLimitNum : 9 }; // 插件配置 $.extend(_oSelf.oConfig, _aoOptions); // 調(diào)用這個對象的方法,傳遞this $.fn.addrInput._initUI.call(_oSelf, event); $.fn.addrInput._initEvents.call(_oSelf); // 提供外部函數(shù) this.close = function () { _close(); } //返回jQuery對象,便于Jquery的鏈?zhǔn)讲僮? return _oSelf; } $.fn.addrInput._initUI = function(event){ var _oSelf = this, _oTarget = $(event.currentTarget); } $.fn.addrInput._initEvents = function(){} })(window.jQuery);
點(diǎn)評
1. 美觀
插件的方法寫在外部,并通過在插件主體傳遞this的方式調(diào)用
2. 定義插件版本號
不過在這里還是沒有用到
3. 關(guān)于call
這里的第一個參數(shù)為傳遞this,后面的均為參數(shù)
語法:
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定義:調(diào)用一個對象的一個方法,以另一個對象替換當(dāng)前對象。
說明:call 方法可以用來代替另一個對象調(diào)用一個方法。call 方法可將一個函數(shù)的對象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對象。如果沒有提供 thisObj 參數(shù),那么 Global 對象被用作 thisObj。
4. 關(guān)于”this”
在插件的方法中,可能有用到指向插件的this、和指向事件觸發(fā)的this,所以事件觸發(fā)的this用event來獲取:event.cuerrntTarget
event.currentTarget:指向事件所綁定的元素,按照事件冒泡的方式,向上找到元素
event.target:始終指向事件發(fā)生時的元素
如:
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); });
結(jié)果輸出
#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>
寫法三(原生寫法)
主體結(jié)構(gòu)
var MemberCard = function(_aoOption){ // 配置(默認(rèn)是從外面?zhèn)鬟M(jìn)來) _aoOption || (_aoOption = {}) ; // 初始化函數(shù) _init(this); } var _init = function(_aoSelf) { // 函數(shù)執(zhí)行 _initData(_aoSelf); // 調(diào)用對象的私有方法 _aoSelf._timedHide(); } var _initData = function ( _aoSelf ) {} // 私有方法 MemberCard.prototype._timedHide = function(_aoOptions) { var _oSelf = this; clearTimeout(this.iHideTimer); // 使用underscore.js的extend方法來實(shí)現(xiàn)屬性覆蓋 var oDefault = extend( { nHideTime: 300 }, _aoOptions ); _oSelf.iHideTimer = setTimeout( function(){ // 調(diào)用對象的共有方法 _oSelf.hide(); }, oDefault.nHideTime); } // 公有方法 MemberCard.prototype.hide = function(_aoOptions) {}
使用
var oColleagueCard = new MemberCard({ nHideTime: 200 }); oColleagueCard.hide();
點(diǎn)評:
1. 關(guān)于屬性覆蓋(對象深拷貝)
原生函數(shù)實(shí)現(xiàn)方法
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個數(shù)組元素 alert(test.b[0]); //不影響test,返回1 alert(test1.b[0]); //返回change
基于jQuery的實(shí)現(xiàn)方法:
jQuery.extend([deep], target, object1, [objectN]);
用一個或多個其他對象來擴(kuò)展一個對象,返回被擴(kuò)展的對象。
如果不指定target,則給jQuery命名空間本身進(jìn)行擴(kuò)展。這有助于插件作者為jQuery增加新方法。 如果第一個參數(shù)設(shè)置為true,則jQuery返回一個深層次的副本,遞歸地復(fù)制找到的任何對象。否則的話,副本會與原對象共享結(jié)構(gòu)。 未定義的屬性將不會被復(fù)制,然而從對象的原型繼承的屬性將會被復(fù)制。
demo:
var options = {id: "nav", class: "header"} var config = $.extend({id: "navi"}, options); //config={id: "nav", class: "header"}
2. 關(guān)于this
這個對象的所有方法的this都指向這個對象,所以就不需要重新指定
寫法四
主體結(jié)構(gòu)
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();
總結(jié)
寫法四和寫法三其實(shí)都差不多,但是你們有沒有看出其中的不一樣呢?
兩種都是利用原型鏈給對象添加方法:
寫法三:
MemberCard.prototype._timedHide MemberCard.prototype.hide
寫法四:
EditorUtil.prototype = { consturctor: EditorUtil, noteBookmark: function(){}, htmlReplace: function(){} }
細(xì)看寫法四利用“對象直接量”的寫法給EditorUtil對象添加方法,和寫法三的區(qū)別在于寫法四這樣寫會造成consturctor屬性的改變
constructor屬性:始終指向創(chuàng)建當(dāng)前對象的構(gòu)造函數(shù)
每個函數(shù)都有一個默認(rèn)的屬性prototype,而這個prototype的constructor默認(rèn)指向這個函數(shù)。如下例所示:
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 // 將上兩行代碼合并就得到如下結(jié)果 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 // 將上兩行代碼合并就得到如下結(jié)果 console.log(p.constructor.prototype.constructor === Person); // true 當(dāng)時當(dāng)我們重新定義函數(shù)的prototype時(注意:和上例的區(qū)別,這里不是修改而是覆蓋),constructor屬性的行為就有點(diǎn)奇怪了,如下示例: 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時,等價于進(jìn)行如下代碼操作:
Person.prototype = new Object({ getName: function() { return this.name; } }); Person.prototype = new Object({ getName: function() { return this.name; } });
而constructor屬性始終指向創(chuàng)建自身的構(gòu)造函數(shù),所以此時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插件制作 手風(fēng)琴Panel效果實(shí)現(xiàn)
- jquery插件制作 圖片走廊 gallery
- jquery插件制作 表單驗證實(shí)現(xiàn)代碼
- 一個簡單的jQuery插件制作 學(xué)習(xí)過程及實(shí)例
- jquery tab插件制作實(shí)現(xiàn)代碼
- jquery插件制作 提示框插件實(shí)現(xiàn)代碼
- jQuery焦點(diǎn)圖切換簡易插件制作過程全紀(jì)錄
- 基于jquery插件制作左右按鈕與標(biāo)題文字圖片切換效果
- jquery插件制作 自增長輸入框?qū)崿F(xiàn)代碼
- jQuery插件制作之全局函數(shù)用法實(shí)例
相關(guān)文章
jquery實(shí)現(xiàn)每個數(shù)字上都帶進(jìn)度條的幻燈片
瀏覽網(wǎng)頁時不小心會碰到這樣的一個網(wǎng)站有幻燈片而且每個數(shù)字上面都帶有進(jìn)度條閑的無聊,自己用jquery實(shí)現(xiàn)了一個,因為有一個進(jìn)度條的播放過程暫不支持ie6,熱愛特效的你可不要錯過了哈2013-02-02jquery實(shí)現(xiàn)清新實(shí)用的網(wǎng)頁菜單效果
這篇文章主要介紹了jquery實(shí)現(xiàn)清新實(shí)用的網(wǎng)頁菜單效果,涉及jquery通過鼠標(biāo)事件控制頁面元素的動態(tài)隱藏與顯示實(shí)現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08基于jQuery實(shí)現(xiàn)的單行公告活動輪播效果
本文通過實(shí)例代碼給大家介紹了基于jQuery實(shí)現(xiàn)的單行公告活動輪播效果,非常不錯,代碼簡單易懂,具有參考借鑒價值,需要的的朋友參考下吧2017-08-08jQuery打字效果實(shí)現(xiàn)方法(附demo源碼下載)
這篇文章主要介紹了jQuery打字效果實(shí)現(xiàn)方法,詳細(xì)分析了jQuery實(shí)現(xiàn)打字效果所涉及的jticker_split.js插件機(jī)具體調(diào)用技巧,并附帶完整的demo源碼供讀者下載參考,需要的朋友可以參考下2015-12-12jQuery1.3.2 升級到j(luò)Query1.4.4需要修改的地方
jQuery1.3.2 升級到 1.4.4 ,需要修改的地方,需要的朋友可以參考下。2011-01-01jquery操作select詳解(取值,設(shè)置選中)
本篇文章主要是對jquery操作select(取值,設(shè)置選中)進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2014-02-02