jQuery插件開發(fā)的五種形態(tài)小結(jié)
關(guān)于jQuery插件的開發(fā)自己也做了少許研究,自己也寫過多個(gè)插件,在自己的團(tuán)隊(duì)了也分享過一次關(guān)于插件的課。開始的時(shí)候整覺的很復(fù)雜的代碼,現(xiàn)在再次看的時(shí)候就清晰了許多。這里我把我自己總結(jié)出來的東西分享出來,幫助那些和我一樣曾經(jīng)遇到過同樣問題的人。
我要做什么
我想要得到的javascript 插件應(yīng)該會(huì)有以下幾個(gè)特征
代碼相對獨(dú)立
鏈?zhǔn)讲僮?br />
插件可配置
有可操作的方法,插件的生命周期可控制
配置可被緩存
可擴(kuò)展
無沖突處理
事件代理,動(dòng)態(tài)初始化
* 以下的代碼均假設(shè)存在 jQuery
插件的第一形態(tài)
面對這種情況,通常我們會(huì)通過定義function的方式來實(shí)現(xiàn)。
function pluginName($selector){
$.each($selector, function () {
$(this).css("background-color", "#ccc");
// to do something...
});
}
// pluginName(document.getElementsByClassName("demo"));
因?yàn)槲艺劦氖莏Query插件開發(fā),那么我現(xiàn)在把這段代碼擴(kuò)展到j(luò)Query上,代碼如下:
// IIFE(立即調(diào)用函數(shù)表達(dá)式); [參考 http://suqing.iteye.com/blog/1981591/]
;(function ($) {
// 擴(kuò)展這個(gè)方法到j(luò)Query.
// $.extend() 是吧方法擴(kuò)展到 $ 對象上,和 $.fn.extend 不同。 擴(kuò)展到 $.fn.xxx 上后,
// 調(diào)用的時(shí)候就可以是 $(selector).xxx()
$.fn.extend({
// 插件名字
pluginName: function () {
// 遍歷匹配元素的集合
// 注意這里有個(gè)"return",作用是把處理后的對象返回,實(shí)現(xiàn)鏈?zhǔn)讲僮?br /> return this.each(function () {
// 在這里編寫相應(yīng)的代碼進(jìn)行處理
});
}
});
// 傳遞jQuery到內(nèi)層作用域去, 如果window,document用的多的話, 也可以在這里傳進(jìn)去.
// })(jQuery, window, document, undefined);
})(jQuery, undefined);
// 調(diào)用方式 $(".selector").pluginName().otherMethod();
但是還差的遠(yuǎn),目前只解決了兩個(gè)問題
代碼相對獨(dú)立插件可配置
鏈?zhǔn)讲僮?br />
有可操作的方法,插件的生命周期可控制
配置可被緩存
可擴(kuò)展
無沖突處理
事件代理,動(dòng)態(tài)初始化
插件的第二形態(tài)
現(xiàn)在來給插件添加參數(shù)支持。代碼如下
;(function($){
$.fn.pluginName = function(options) {
// 合并參數(shù),通過“extend”合并默認(rèn)參數(shù)和自定義參數(shù)
var args = $.extend({}, $.fn.pluginName.defaults, options);
return this.each(function() {
console.log(args.text);
// to do something...
});
};
// 默認(rèn)參數(shù)
$.fn.pluginName.defaults = {
text : "hello"
};
})(jQuery);
// $(".selector").pluginName({
// text : "hello world!"
// });
添加參數(shù)支持還比較容易些,又解決一問題
代碼相對獨(dú)立有可操作的方法,插件的生命周期可控制
鏈?zhǔn)讲僮?br />
插件可配置
配置可被緩存
可擴(kuò)展
無沖突處理
事件代理,動(dòng)態(tài)初始化
插件的第三形態(tài)
現(xiàn)在來添加方法的支持,我前面所提到的生命周期可控制,意思差不多,例如添加reInit,destory等方法來控制插件。
;(function($){
$.fn.pluginName = function (method) {
// 如果第一個(gè)參數(shù)是字符串, 就查找是否存在該方法, 找到就調(diào)用; 如果是object對象, 就調(diào)用init方法;.
if (methods[method]) {
// 如果存在該方法就調(diào)用該方法
// apply 是吧 obj.method(arg1, arg2, arg3) 轉(zhuǎn)換成 method(obj, [arg1, arg2, arg3]) 的過程.
// Array.prototype.slice.call(arguments, 1) 是把方法的參數(shù)轉(zhuǎn)換成數(shù)組.
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
// 如果傳進(jìn)來的參數(shù)是"{...}", 就認(rèn)為是初始化操作.
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.pluginName');
}
};
// 不把方法擴(kuò)展在 $.fn.pluginName 上. 在閉包內(nèi)建個(gè)"methods"來保存方法, 類似共有方法.
var methods = {
/**
* 初始化方法
* @param _options
* @return {*}
*/
init : function (_options) {
return this.each(function () {
var $this = $(this);
var args = $.extend({}, $.fn.pluginName.defaults, _options);
// ...
})
},
publicMethod : function(){
private_methods.demoMethod();
}
};
// 私有方法
function private_methods = {
demoMethod : function(){}
}
// 默認(rèn)參數(shù)
$.fn.pluginName.defaults = {
};
})(jQuery);
// 調(diào)用方式
// $("div").pluginName({...}); // 初始化
// $("div").pluginName("publicMethod"); // 調(diào)用方法
又解決一問題
代碼相對獨(dú)立配置可被緩存
鏈?zhǔn)讲僮?br />
插件可配置
有可操作的方法,插件的生命周期可控制
可擴(kuò)展
無沖突處理
事件代理,動(dòng)態(tài)初始化
插件的第四形態(tài)
第三形態(tài)的插件修改就已經(jīng)可以應(yīng)對大多數(shù)插件的需求了。精益求精嘛,繼續(xù)升級。
第四形態(tài)的插件是照幫司徒正美的《javascript框架設(shè)計(jì)》的代碼。加了點(diǎn)面向?qū)ο蟮闹R(shí)。
(function ($) {
var Plugin = function (element, options) {
this.element = element;
this.options = options;
};
Plugin.prototype = {
create: function () {
console.log(this.element);
console.log(this.options);
}
};
$.fn.pluginName = function (options) {
// 合并參數(shù)
return this.each(function () {
// 在這里編寫相應(yīng)的代碼進(jìn)行處理
var ui = $._data(this, "pluginName");
// 如果該元素沒有初始化過(可能是新添加的元素), 就初始化它.
if (!ui) {
var opts = $.extend(true, {}, $.fn.pluginName.defaults, typeof options === "object" ? options : {});
ui = new Plugin(this, opts);
// 緩存插件
$._data(this, "pluginName", ui);
}
// 調(diào)用方法
if (typeof options === "string" && typeof ui[options] == "function") {
// 執(zhí)行插件的方法
ui[options].apply(ui, args);
}
});
};
$.fn.pluginName.defaults = {};
})(jQuery);
// 調(diào)用的方式和之前一樣。
這里特別要提下緩存這個(gè)東西,插件用多了,覺的這個(gè)真的是好東西。
在傳統(tǒng)面向?qū)ο蟮牟寮_發(fā)中,至少會(huì)聲明個(gè)變量保存它,但是我到目前寫的jQuery插件中都沒有,用起來很麻煩。自從把初始化后的插件緩存起來后,方便了許多。通過代碼$("#target").data("pluginName")就可以取到對象了。 來看看還有什么問題沒有解決
代碼相對獨(dú)立可擴(kuò)展
鏈?zhǔn)讲僮?br />
插件可配置
有可操作的方法,插件的生命周期可控制
配置可被緩存
無沖突處理
事件代理,動(dòng)態(tài)初始化
插件的第五形態(tài)
看了上面的代碼是否腦子有點(diǎn)暈了,如果是,休息片刻,稍后回來,下面的代碼更精彩。 最后一個(gè)方案算是比較全面的了。方案來自Bootstrap,下面代碼以 Bootstrap 的 button 插件為例.
!function ($) {
// ecma262v5 的新東西, 強(qiáng)制使用嚴(yán)謹(jǐn)?shù)拇a編寫.
"use strict";
// BUTTON PUBLIC CLASS DEFINITION
// ==============================
var Button = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, Button.DEFAULTS, options);
};
Button.DEFAULTS = {
loadingText: 'loading...'
};
Button.prototype.setState = function (state) {
// ...
};
Button.prototype.toggle = function () {
// ...
};
// BUTTON PLUGIN DEFINITION
// ========================
var old = $.fn.button; // 這里的 $.fn.button 有可能是之前已經(jīng)有定義過的插件,在這里做無沖突處理使用。
$.fn.button = function (option) {
return this.each(function () {
var $this = $(this);
// 判斷是否初始化過的依據(jù)
var data = $this.data('bs.button');
var options = typeof option == 'object' && option;
// 如果沒有初始化過, 就初始化它
if (!data) $this.data('bs.button', (data = new Button(this, options)));
if (option == 'toggle') data.toggle();
else if (option) data.setState(option)
})
};
// ① 暴露類名, 可以通過這個(gè)為插件做自定義擴(kuò)展
$.fn.button.Constructor = Button;
// 擴(kuò)展的方式
// 設(shè)置 : $.fn.button.Constructor.newMethod = function(){}
// 使用 : $btn.button("newMethod");
// ② 無沖突處理
$.fn.button.noConflict = function () {
$.fn.button = old;
return this
};
// ③ 事件代理, 智能初始化
$(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
var $btn = $(e.target);
// 查找要初始化的對象
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn');
// 直接調(diào)用方法, 如果沒有初始化, 內(nèi)部會(huì)先進(jìn)行初始化
$btn.button('toggle');
e.preventDefault();
});
}(jQuery);
來看看還有什么問題沒有解決
代碼相對獨(dú)立
鏈?zhǔn)讲僮?br />
插件可配置
有可操作的方法,插件的生命周期可控制
配置可被緩存
可擴(kuò)展
無沖突處理
事件代理,動(dòng)態(tài)初始化
補(bǔ)充
現(xiàn)在的插件都要求靈活性要高,比如希望插件可以同時(shí)適配jQuery和Zepto,又或者需要支持AMD或者CMD規(guī)范。
支持jQuery和Zepto
if (window.jQuery || window.Zepto) {
(function ($) {
// plugin code...
})(window.jQuery || window.Zepto);
}
中間件支持,node
if (typeof(module) !== 'undefined')
{
module.exports = pluginName;
}
requirejs(AMD) support
if (typeof define === 'function' && define.amd) {
define([], function () {
'use strict';
return pluginName;
});
}
seajs(CMD) support
if (typeof define === 'function') {
define([], function () {
'use strict';
return pluginName;
});
}
呼~,問題都解決了,代碼若有看不懂的地方可以多看看。后面的幾個(gè)看不懂也沒有關(guān)系,在實(shí)際的開發(fā)中,前面幾個(gè)夠用了。要強(qiáng)調(diào)下,并不是越高級的寫法越好,要看自己項(xiàng)目的需求合理的選擇。
好了,今天的總結(jié)就先到這里了,如果大家有更好的插件開發(fā)方式,還請告知一下。希望大家能夠喜歡本文。
- 跟我一起學(xué)寫jQuery插件開發(fā)方法(附完整實(shí)例及下載)
- jQuery插件開發(fā)的兩種方法及$.fn.extend的詳解
- 基于Jquery插件開發(fā)之圖片放大鏡效果(仿淘寶)
- jQuery插件開發(fā)詳細(xì)教程
- jquery插件開發(fā)方法(初學(xué)者)
- 跟我一起學(xué)JQuery插件開發(fā)
- 自己動(dòng)手開發(fā)jQuery插件教程
- jQuery圖片輪播插件——前端開發(fā)必看
- jQuery圖片查看插件Magnify開發(fā)詳解
- jQuery 驗(yàn)證插件 Web前端設(shè)計(jì)模式(asp.net)
- jquery插件開發(fā)模式實(shí)例詳解
相關(guān)文章
jquery.hotkeys監(jiān)聽鍵盤按下事件keydown插件
jquery.hotkeys就是網(wǎng)頁是監(jiān)聽用戶按鍵要用到的jquery庫,這里簡單介紹下使用方法,需要的朋友可以參考下2014-05-05基于jquery fly插件實(shí)現(xiàn)加入購物車拋物線動(dòng)畫效果
在購物網(wǎng)站中,加入購物車的功能是必須的功能,有的網(wǎng)站在用戶點(diǎn)擊加入購物車按鈕時(shí),就會(huì)出現(xiàn)該商品從點(diǎn)擊出以拋物線的動(dòng)畫相似加入購物車,這個(gè)功能看起來非常炫,對用戶體驗(yàn)也有一定的提高。下面介紹基于jquery fly插件實(shí)現(xiàn)加入購物車拋物線動(dòng)畫效果2016-04-04jQuery實(shí)現(xiàn)鼠標(biāo)選文字發(fā)新浪微博的方法
這篇文章主要介紹了jQuery實(shí)現(xiàn)鼠標(biāo)選文字發(fā)新浪微博的方法,涉及jQuery鼠標(biāo)事件的響應(yīng)及新浪接口的調(diào)用技巧,非常簡單實(shí)用的功能,需要的朋友可以參考下2016-04-04基于jquery的DIV隨滾動(dòng)條滾動(dòng)而滾動(dòng)的代碼
基于jquery的DIV隨滾動(dòng)條滾動(dòng)而滾動(dòng)的代碼,有了JQuery簡單多了,就幾行代碼搞定2012-07-07幾行代碼輕松搞定jquery實(shí)現(xiàn)flash8類似的連接效果
幾行代碼輕松搞定jquery實(shí)現(xiàn)flash8類似的連接效果...2007-05-05基于jquery1.4.2的仿flash超炫焦點(diǎn)圖播放效果
有了jquery一切變的如此簡單!讓js做的動(dòng)畫更有動(dòng)感。2010-04-04使用簡潔的jQuery方法實(shí)現(xiàn)隔行換色功能
本篇文章主要介紹了使用簡潔的jQuery方法實(shí)現(xiàn)隔行換色功能。需要的朋友可以過來參考下,希望對大家有所幫助2014-01-01