2016-01-13 26 views
4

哇,我在StackOverflow上的第一個問題!jQuery UI的部件「銷燬」方法 - 不一致的錯誤

對於那裏的jQuery UI主人,我被困在這一個,這需要很多。我已經閱讀了所有的api文檔,並繼續空着。

所以,這個例子非常簡單,不用擔心爲什麼我這樣做,我只是尋找一個解釋,當在一個小部件上調用jQuery UI的.destroy()方法時出現簡單的不一致。


在我的第一示例中,我請日期選擇器插件的destroy方法,然後重新初始化元件作爲一個datepicker插件。正如我所料,這是有效的。由於datepicker當前不存在,因此將忽略destroy方法,並創建日期選擇器窗口小部件。

$("#datepicker").datepicker("destroy").datepicker(); 

在我的第二個例子中,我選擇了另一個小部件,這次是一個按鈕。我嘗試了與第一個示例中相同的方法,除了這次,我收到一個錯誤,錯誤:無法在初始化之前調用按鈕上的方法;試圖調用方法 '破壞'

$("#button").button("destroy").button(); 

那麼,如何以及爲什麼會出現這種情況?文檔中的這兩個部件的讀取方式完全相同datepicker; button。我覺得奇怪的是,它只能用於日期選擇器小部件而不是所有其他原生jQuery UI小部件。


萬一有人好奇,我能夠重現在Chrome 47.0.2526.106米& IE 11.0.9600.18097相同的結果(更新11.0.25)


此外,爲了對你來說很簡單,下面是一個工作代碼片斷,它顯示了兩個例子,第一個例子工作,第二個例子拋出元素下方顯示的錯誤。爲了探索所有選項,我繼續前進,並在對話框小部件中向片段添加了第三個示例,並收到相同的錯誤。

(function ($){ 
 
    try { 
 
    $("#datepicker").datepicker("destroy").datepicker(); 
 
    } 
 
    catch (e) { 
 
    $("#datepickerError").html(e); 
 
    } 
 
    
 
    try { 
 
    $("#button").button("destroy").button(); 
 
    } 
 
    catch (e) { 
 
    $("#buttonError").html(e); 
 
    } 
 
    
 
    try { 
 
    $("#dialog").dialog("destroy").dialog(); 
 
    } 
 
    catch (e) { 
 
    $("#dialogError").html(e); 
 
    } 
 
})(window.jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<link href="https://code.jquery.com/ui/1.11.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/> 
 
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script> 
 

 

 
<input type="text" id="datepicker" /> 
 
<br /> 
 
<span id="datepickerError">(no error)</span> 
 
<br /><br /> 
 
<input type="button" id="button" value="Button" /> 
 
<br /> 
 
<span id="buttonError">(no error)</span> 
 
<br /> 
 
<br /> 
 
<div id="dialog" title="test"></div> 
 
<br /> 
 
<span id="dialogError">(no error)</span>

回答

1

我相信這是因爲DatePicker的是不是在這個意義上真正的jQuery插件,它不使用控件工廠像其他的人做的。它使用$.fn原型來定義它自己。從代碼它這樣做是爲了創建日期選擇器方法

$.fn.datepicker = function(options){ 

而部件工廠部件與部件廠註冊自己與工廠處理創建方法:

$.widget("ui.button", { .... }); 

事實上,我相信它仍處於他們使用Widget工廠重寫它的路徑。

http://wiki.jqueryui.com/w/page/12137778/Datepicker

The specific code and functionality changes we want to address in this refactor are:

Refactor the code to use the widget factory and follow the jQuery UI API

窗口小部件工廠是處理所有的部件法寶,其中之一是找到的元素實例窗口小部件已呼籲和或確定不是如果它被實例化並顯示的東西錯誤。但是由於DatePicker不使用Widget工廠,它可能不會因爲Widget工廠錯誤而失敗,並且最有可能優雅地失敗,因爲大多數jQuery的東西在你正在操作的jquery對象中沒有元素時會做。

事實上,如果您取消選擇jquery ui下載中的所有內容,並且只選擇DatePicker以及它所需的任何依賴關係。看看下載的文件。 Widget工廠甚至沒有包含在內,並且是錯誤消息。現在在UI Core下檢查小部件並再次下載它。再次搜索該錯誤消息。它是!在$.widget.bridge函數下。

if (!instance) { 
    return $.error("cannot call methods on " + name + " prior to initialization; " + 
    "attempted to call method '" + options + "'"); 
} 

如果我們看看日期選擇器代碼,你可以看到當你通過它的選項,它會嘗試在某些情況下建立方法名稱。其中之一是_destroyDatepicker。有直接沒有代碼,從當元素都沒有被實例化的日期選擇器調用任何如此它建立一個函數名和調用函數,並在銷燬前幾行之一是

if (!$target.hasClass(this.markerClassName)) { 
    return; 
} 
停止它的 $.fn擴展功能

因此,這很可能會在沒有任何錯誤的情況下進行保護。

總之,你是對的。這是不一致的。有一個原因,但除非你熟悉他們的代碼,否則根本不明顯。

+1

良好的捕獲,並非常有趣,他們的日期選擇器不使用小工廠。我想我只是假設它正在使用Widget工廠,就像所有其他Widget一樣。有趣的是,我更喜歡datepicker的當前功能,我希望他們能讓其他小部件以這種方式工作。這可能是我做一些自定義jQuery的時候了;-)感謝您的詳細回覆,非常感謝! –

+0

@HowardRenollet沒問題!出於興趣,你爲什麼喜歡日期選擇器更好?由於那個錯誤?如果僅僅是這個錯誤,你可以在調用一個小部件函數來確定它是否被實例化之前,檢查元素上的小部件實例數據。我想只是做$(element).data('ui-widgetname')並且看它是否返回任何東西。 – AtheistP3ace

+0

我一直習慣於在元素上調用任何方法一段時間之前檢查它是否存在。然而,我在別人的代碼中發現了這一點,我正在調整,並且很好奇爲什麼它實際上工作,但只爲datepicker。我可以看到兩種方式都有好處......如果您不希望對不存在的元素調用方法,那麼很容易出錯,但是,我的情況是獨一無二的,當我真正期望元素在代碼第一次運行時不存在,但每隔一段時間,它都會實際銷燬並重新創建該小部件作爲乾淨的實例。 –