[英]Is there a better way/pattern to write this jQuery plugin?
我有一個相當復雜的搜索插件:它具有不同版本的UI和功能,以及相互依賴的domElements中的一堆。 插件的多個實例將立即存在於頁面上。
我正在使用基本的jQuery創作模式: http : //docs.jquery.com/Plugins/Authoring
為了保存選項,相互依賴的事件以及跨多個對象的各種dom查找,我將有問題的元素傳遞給每個函數,並將狀態/選項/相互依賴性存儲在我每次檢索的數據屬性中。 它可以工作,並防止事件發生沖突,但編寫代碼似乎是一種混亂的方式。
跨多個實例存儲狀態的最佳方法是什么? 我這樣做的方式是一個巨大的矯枉過正,我錯過了什么? 它可能源於我在jQuery插件模式中創建類對象的誤解。
(function($) {
var _options = {};
var methods = {
init: function(options) {
return this.each(function() {
if (options) {
_options = $.extend($.fn.examplePlugin.defaults, options);
} else {
_options = $.fn.examplePlugin.defaults;
}
$this = $(this);
var data = $this.data('examplePlugin');
if (!data) {
$this.data('examplePlugin', {
target: $this
});
$.each(_options, function(key, value){
$this.data('examplePlugin')[key] = value;
});
data = $this.data('examplePlugin');
}
//Cache dom fragment plugin is in (if passed)
if (data.domContextSelector == null || data.domContextSelector == "") {
data.domContext = $(body);
} else {
data.domContext = $(data.domContextSelector);
}
init($this);
});
}
};
var init = function(element) {
data = getData(element);
//Storing dom elements to avoid lookups
data.relatedElement = $(data.relatedElementSelector, data.domContext);
element.click(function(event){
doSomethingCool($(event.currentTarget));
});
};
var doSomethingCool = function(element) {
data = getData(element);
element.slideUp();
data.relatedElement.slideDown();
};
var adjustHeight = function(element) {
data = getData(element);
element.height(data.relatedElement.height());
};
var getData = function(element) {
return $(element).data('examplePlugin');
};
$.fn.examplePlugin = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
}
else {
$.error('Method ' + method + ' does not exist on jQuery.examplePlugin');
}
return false;
};
$.fn.examplePlugin.defaults = {
defaultA: 'something',
relatedElementSelector: '#related',
domContextSelector: 'header.header'
};})(jQuery);
是的,如果你按照jQuery指南,你正在構建它根據它應該如何構建並利用它的設計目的(特別是鏈接)。
但是,我不一定遵循這條道路。 你可以通過很多方法來完成這些插件, 比如這個為jQuery插件制作樣板的人,它不是基於jQuery的設計,而是基於OOP的角度(我更喜歡)。 我認為它更干凈,但是犧牲了不遵循通常的語法( element.myPlugin({options})
並且無法鏈接(直到你修改了一下)
同一個人有一個較舊的帖子,這是通常的jQuery插件設計的樣板。
就個人而言,我建議堅持jQuery團隊推薦的插件設計模式。 它有助於保持一致性,並使您的插件更加社區友好。
話說回來...
我遇到了試圖保持多個元素狀態的問題。 我發現的一個解決方案是使用jQuery Data API (看起來像這樣: $( selector ).data( key, value )
)來保存元信息,如元素的狀態或應用程序狀態。
使用data()的好處在於它不會更新/訪問DOM,而是使用jQuery的內部元素,因此訪問速度比嘗試存儲信息隱藏輸入字段,更改類名或執行其他時髦技巧更快開發人員試圖用來在客戶端上存儲數據。 (請記住,您不需要使用HTML5文檔類型來使用數據API,但如果您執行數據 - *鍵屬性非常有幫助 !)
當所有元素都有自己的狀態但當前元素是控制整個插件狀態的元素時,它會變得棘手。 對於這種情況,我使用body標簽來存儲當前元素的數據 ,如下所示:
$('body').data('myPluginNameSpace.current', selectorRef );
這樣,當我需要檢查我的插件/頁面/應用程序的狀態,或者監聽我冒泡到文檔對象的插件特定事件時,我可以快速查找當前/所選元素,並應用任何UI更改或行為:
var currentElementRef = $('body').data('myPluginNameSpace.current');
doFunStuff( currElementRef );
您還可以通過許多其他方式執行此操作,例如創建自定義Event對象並將自定義參數附加到其中 :
var myPluginEvent = jQuery.Event( 'customEvent.myPluginNameSpace', { myProp : myValue });
$( document ).trigger( myPluginEvent );
當您的自定義事件被觸發並稍后通過回調函數處理時,您的自定義參數將附加到傳遞給處理程序的事件對象:
$( document ).on( 'customEvent.myPluginNameSpace', function( e ){
doStuff( e.myProp ); //you can access your custom properties attach to the event
});
您可以通過許多不同的道路到達同一個目的地; 這就是JavaScript的美麗和恐怖。
在您的特定情況下請記住,您不必讓所有內部運行都return this.each({ })
您的插件的methods.init函數的return this.each({ })
部分:
例如,除非您為每個元素設置特定選項,否則我將取出您為每個元素擴展選項對象的部分!
var methods = {
init: function(options) {
//DO OPTIONS/EVENTLISTENER/etc STUFF OUT HERE
return this.each(function() {
//DONT DO THIS
if (options) {
_options = $.extend($.fn.examplePlugin.defaults, options);
} else {
_options = $.fn.examplePlugin.defaults;
}
試試這個:
...
var methods = {
init : function( options ){
//do setup type stuff for the entire Plugin out here
var _options = $.MyPlugin.options = $.extend( defaults, options );
//add some listeners to $(document) that will later be handled
//but put them in an external function to keep things organized:
//methods.addListeners()
//this refers to the array of elements returned by $(selector).myPlugin();
//this.each() iterates over, EACH element, and does everything inside (similar to Array.map())
//if the selector has 100 elements youre gonna do whats in here 100 times
return this.each(function(){
//do function calls for individual elements here
});
},
此外,利用自定義事件將幫助您! 向文檔對象添加一些事件偵聽器,讓事件處理程序使用數據API或自定義事件參數確定要與哪個元素進行交互。
我在查看我的插件如何保存狀態時發現了你的推文,同時學習了本教程中的插件開發: http : //tutsplus.com/lesson/head-first-into-plugin-development/
在這個龐大的課程中,我們將深入研究jQuery插件開發。 在此過程中,我們將審查各種最佳實踐和技術,以便為插件用戶提供最高級別的靈活性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.