插件實(shí)現(xiàn)方式
1胯府、聲明立即調(diào)用函數(shù)
+function($){"use strict",......}(jquery)
定義一個(gè)立即調(diào)用的函數(shù)聲明秋秤,如代碼清單2-1所示宏粤。在參數(shù)里傳入jQuery對象,通過參數(shù)$引入變量
灼卢,這樣其所有代碼在使用jQuery的時(shí)候绍哎,直接使用$符即可。這樣的做法鞋真,有以下兩個(gè)好處:?函數(shù)內(nèi)部的$符變量代表了局部變量崇堰,而不是全局變量里代表jQuery的$符變量,以達(dá)到防止變量污染的目的涩咖。?內(nèi)部的代碼全部都是私有代碼海诲,外部代碼無法訪問,只有通過第三步檩互,在$.fn上設(shè)置了插件(比如$.fn.alert=)的形式特幔,通過$符變量才能將整個(gè)插件通過唯一的接口$.fn.alert暴露出去,從而保護(hù)了其內(nèi)部代碼闸昨。
+function ($) {
"use strict";// 1.使用嚴(yán)格模式ES5支持
// 2.alert插件類及原型方法的定義
// 3.在jQuery上定義alert插件,并重設(shè)插件構(gòu)造器
// 重設(shè)插件構(gòu)造器,可以通過該屬性獲取插件的真實(shí)類函數(shù)
// 4. 防沖突處理
// 5. 綁定觸發(fā)事件
}(window.jQuery);
注意:在function關(guān)鍵字前面有一個(gè)加號(hào)運(yùn)算符(+)蚯斯,其主要目的是防止前面有未正常結(jié)束的代碼(通常是遺漏了分號(hào)),導(dǎo)致前后代碼被編譯器認(rèn)為是一體的零院,從而導(dǎo)致代碼運(yùn)行出錯(cuò)溉跃。
2村刨、定義相關(guān)插件類及原型方法
例如:alert prototype.close
步驟2 定義該插件的核心代碼告抄,也就是在觸發(fā)特定行為(通常是單擊行為)后要進(jìn)行處理的代碼。插件核心代碼示例// alert插件類及原型方法的定義// 定義選擇器,所有符合該自定義屬性的元素都可以觸發(fā)下面的事件
var dismiss = '[data-dismiss="alert"]'var Alert = function (el) {
// 傳入元素,如果元素內(nèi)部有dismiss上設(shè)置的自定義屬性,則click事件會(huì)觸發(fā)原型上的
close方法
$(el).on('click', dismiss, this.close)
}
Alert.prototype.close = function (e) { // 關(guān)閉警告框的主要代碼設(shè)置,每一行代碼的細(xì)節(jié)注釋,請參考5.8節(jié)}
通過上述代碼可以看出嵌牺,主要是先定義了插件插件的類函數(shù)Alert打洼,然后再定義需要用到的一些原型函數(shù),比如close函數(shù)方法逆粹。Alert函數(shù)接收el參數(shù)募疮,el表示DOM元素,一個(gè)DOM如果綁定了data-dismiss="alert"自定義屬性僻弹,則在單擊的時(shí)候就會(huì)觸發(fā)close函數(shù)方法阿浓,從而達(dá)到關(guān)閉的目的。同樣蹋绽,Modal插件也是先定義Modal類函數(shù)芭毙,然后再在Modal的原型上定義toggle和show等方法筋蓖,其內(nèi)部根據(jù)相應(yīng)的規(guī)則再細(xì)化處理。
3退敦、在jquery上定義插件粘咖,并重設(shè)插件構(gòu)造函數(shù)
例如:$.fn.alert.Constructor=Alert
在jQuery上定義插件,以便通過jQuery.插件名稱的方式侈百,也能夠使用該插件瓮下,也就是在觸發(fā)特定行為(通常是單擊行為)后要進(jìn)行處理的通用代碼。最后在這里再調(diào)用插件類或原型方法钝域。主要源碼如代碼清單2-3所示讽坏。代碼清單2-3jQuery插件定義// 在jQuery上定義alert插件,并重設(shè)插件構(gòu)造器var old = $.fn.alert// 保留其他插件的$.fn.alert代碼(如果定義),以便在noConflict之后,可以繼續(xù)使用該舊代碼$.fn.alert = function (option) {
return this.each(function () {
// 根據(jù)選擇器,遍歷所有符合規(guī)則的元素,然后在元素上綁定插件的實(shí)例,以監(jiān)控用戶的事件行為
})
}
$.fn.alert.Constructor = Alert;// 并重設(shè)插件構(gòu)造器,可以通過該屬性獲取插件的真實(shí)類函數(shù)
jQuery插件的定義使用了標(biāo)準(zhǔn)的方法,在fn上進(jìn)行擴(kuò)展例证。在附加擴(kuò)展之前震缭,首先“備份”之前插件(或別的框架提供的同名插件)的舊代碼,以方便在后面防沖突的時(shí)候使用战虏。在附加擴(kuò)展之后拣宰,重新設(shè)置插件的構(gòu)造器(即Constructor屬性)為內(nèi)部定義的插件類函數(shù)自身,這樣就可以通過Constructor屬性查詢到插件的真實(shí)類函數(shù)烦感,使用new操作符實(shí)例化$.fn.alert的時(shí)候也不會(huì)出錯(cuò)花枫。
注意:即便不聲明第三步,HTML聲明式的方式也是可以用的乌企。所以說拱层,第三步是專門為某些喜歡用JavaScript代碼觸發(fā)事件的人所準(zhǔn)備的。但需要注意的是绿渣,如果不聲明第三步朝群,那第四步的防沖突的功能也就沒法用了。
4中符、防止沖突處理
例如:$.fn.alert.noConflict
防沖突處理姜胖,目的是讓Bootstrap插件和其他UI庫的同名插件共存。Bootstrap所有的插件都支持防沖突(noConflict)功能淀散。源碼如代碼清單2-4所示右莱。
// 防沖突處理
$.fn.alert.noConflict = function () {
$.fn.alert = old // 恢復(fù)以前的舊代碼
return this // 將$.fn.alert.noConflict()設(shè)置為Bootstrap的alert插件
}
這樣一旦有了一個(gè)同名的插件,比如A庫里有個(gè)同名$.fn.alert插件档插,則Bootstrap在執(zhí)行之前就通過old先備份了慢蜓,然后執(zhí)行$.fn.alert.noConflict()后就會(huì)還原該old對象插件;而使用Bootstrap的alert插件的話郭膛,則通過varalert=$.fn.alert.noConflict()的形式晨抡,將Bootstrap的alert插件轉(zhuǎn)移到另外一個(gè)變量上,從而進(jìn)行使用。
5耘柱、綁定各種觸發(fā)事件
在一切都就緒之后圆雁,綁定默認(rèn)的觸發(fā)事件。由于已經(jīng)為jQuery提供了默認(rèn)的$.fn.alert擴(kuò)展插件功能帆谍,已經(jīng)可以通過手工編寫JavaScript代碼來觸發(fā)事件了伪朽。這里的第五步主要是為聲明式的HTML觸發(fā)事件,即:在HTML文檔里已經(jīng)按照布局規(guī)則聲明了相關(guān)的自定義屬性(比如data-dismiss="alert")汛蝙,然后通過這里的代碼初始化默認(rèn)的單擊事件行為(或其他相關(guān)插件需要用到的行為)烈涮。綁定觸發(fā)事件的源碼如下所示:
// 綁定觸發(fā)事件
// 為聲明式的HTML綁定單擊事件
// 在整個(gè)document對象上,檢測是否有自定義屬性data-dismiss="alert"
// 如果有,則設(shè)置:單擊的時(shí)候,關(guān)閉指定的警告框元素
$(document).on('click.bs.alert.dataapi',dismiss, Alert.prototype.close)
上述代碼在整個(gè)document文檔上檢測自定義屬性datadismiss="alert"窖剑,如果有坚洽,則綁定click單擊事件(在命名空間bs.alert.data-api上),事件回調(diào)函數(shù)則是原型方法Alert.prototype.close西土。這樣讶舰,一旦單擊了相應(yīng)的元素,就會(huì)關(guān)閉特定的警告框需了。
Bootstrap通過這5個(gè)通用步驟跳昼,定義了所有的插件。每個(gè)插件在各個(gè)步驟里會(huì)有一些細(xì)節(jié)的不同肋乍,但思路都是一樣的鹅颊,那就是:綁定事件,觸發(fā)行為墓造,并在jQuery上擴(kuò)展fn堪伍,同時(shí)解決防沖突的問題。大家在制作自定義插件的時(shí)候只要遵從這一思路觅闽,即可編寫出既易于維護(hù)又高質(zhì)量的插件代碼帝雇。
2.4.3 通用技術(shù)根據(jù)上述JavaScript插件的實(shí)現(xiàn)步驟,來總結(jié)一下JavaScript插件的通用技術(shù)蛉拙,即Bootstrap的開發(fā)者在開發(fā)這些插件時(shí)所制定的規(guī)則和遵循的標(biāo)準(zhǔn)尸闸,同時(shí)也為我們制作自定義插件提供有力的參考。首先刘离,不同插件的JS代碼都是單獨(dú)放在一個(gè)JS文件中的室叉,開發(fā)人員在使用的時(shí)候可以一次性編譯到Bootstrap.js,也可以單獨(dú)使用某一個(gè)或者多個(gè)JS插件文件硫惕。唯一需要注意的是:有些JS插件依賴于其他JS插件,所以不要遺漏了依賴引用野来。Bootstrap所有的JavaScript插件都可以通過配置使用恼除,即通過特定的HTML設(shè)置,而不需要任何JavaScript再次觸發(fā)。但如果需要啟用手動(dòng)觸發(fā)事件的行為豁辉,可以禁用默認(rèn)的行為令野,禁用方法非常簡單,只需要將body元素上的命名空間為data-api下的全部事件禁用即可徽级。代碼如下所示:
$(document).off('.data-api');
如果想禁用特定插件的默認(rèn)行為气破,只需要禁用該插件所在命名空間下的事件即可。代碼如下所示:
$(document).off('.alert.data-api');
/* 禁用alert插件的所有默認(rèn)行為 */
注意off語法是jQuery提供的語法功能餐抢,用戶在使用on進(jìn)行綁定事件的時(shí)候现使,可以加命名空間,比如
$().on('click.alert.dataapi')
這樣在卸載事件的時(shí)候旷痕,如果只想卸載該元素的該特定事件碳锈,可以使用off('click.alert.data-api')。如果不這樣欺抗,僅僅使用off('click')售碳,這樣該元素上的所有click事件都將被卸載(導(dǎo)致該元素的其他click事件失效)。同理绞呈,如果執(zhí)行off('.data-api')代碼贸人,則所有在data-api命名空間下的事件都會(huì)被卸載禁用,不管是該選擇器內(nèi)部的哪個(gè)元素佃声、哪種事件灸姊。
1.可編程性所有的插件不僅可以使用聲明式定義(HTML),也可以通過JavaScript代碼全部實(shí)現(xiàn)秉溉。利用jQuery的鏈?zhǔn)讲僮髁撸幊龅拇a非常優(yōu)美。示例如下所示:
$(".btn.btn-danger").button("toggle").addClass("fat");
所有的插件在使用JavaScript代碼調(diào)用的時(shí)候召嘶,都提供多種調(diào)用方式:無參數(shù)傳遞(即默認(rèn)方式)父晶、傳遞對象字面量進(jìn)行初始化參數(shù)設(shè)定、直接傳入一個(gè)需要執(zhí)行的方法名稱字符串弄跌。示例如下所示:
$("#myModal").modal() // 默認(rèn)值進(jìn)行初始化
$("#myModal").modal({ keyboard: false }) // 初始化時(shí)keyboard選項(xiàng)值是false
$("#myModal").modal('show') // 初始化,然后立即調(diào)用show方法
每個(gè)插件都有一個(gè)Constructor屬性甲喝,用于表示原始的構(gòu)造函數(shù),比如$.fn.alert.Constructor铛只。另外也可以通過$('選擇符').data('bs.插件名稱')的形式(如埠胖,$('[datadismiss="alert"]').data('bs.alert'))獲取該特定插件的實(shí)例。
2.防沖突和jQuery一樣淳玩,Bootstrap插件可以和其他同類插件共存直撤,為了防止$.fn.下的Bootstrap插件被覆蓋,Bootstrap也提供了防沖突功能(No conflict)蜕着,用于定義別名谋竖。示例用法如下:
var bootstrapButton = $.fn.button.noConflict()// 返回$.fn.button對象給bootstrapButton變量
$.fn.bootstrapBtn = bootstrapButton// 將button對象給bootstrapButton變量賦予一個(gè)新插件名稱
$().bootstrapBtn,這時(shí)$().// bootstrapBtn就擁有了先前button的所有功能了
3.自定義事件Bootstrap為很多插件都提供了自定義事件功能红柱,比如,modal彈窗里提供的show和shown事件蓖乘,show事件在彈窗初始化(即將彈出)的時(shí)候觸發(fā)锤悄,而shown事件則是在彈窗初始化完畢后(完全彈出)才觸發(fā)。在新版插件里嘉抒,所有的事件都是命名空間化的零聚,即單個(gè)事件都要放在某個(gè)命名空間下,比如些侍,show.bs.modal隶症。所有的插件都提供了preventDefault功能,用于阻止繼續(xù)執(zhí)行后續(xù)的代碼娩梨。例如沿腰,可以在modal彈窗的show事件里進(jìn)行判斷,如果不符合條件就拒絕顯示彈窗狈定。示例代碼如下所示:
$('#myModal').on('show.bs.modal', function (e) {
if (!data) return e.preventDefault() // 拒絕顯示彈窗
})