2014-07-27 92 views
1

我一直在爲一個項目工作一些JavaScript,並決定它應該是一個jQuery插件。我之前寫過一些,但這需要更強大和可銷燬。爲此,我遵循了幾個教程,但是在描述如何銷燬插件時,這些教程都不盡人意。無法銷燬jQuery插件

那麼我該如何銷燬插件?我似乎無法訪問$('.js-target).fullscreen('destroy')似乎沒有工作。 $(.js-target).data('fullscreen').destroy()也不在控制檯中返回TypeError: Cannot read property 'destroy' of undefined

我已經寫在咖啡腳本。生成的javascript發佈在下面。

(($, window) -> 

    'use strict' 

    # Create the defaults once 
    pluginName = 'fullscreen' 
    defaults = 
    reference: window 
    offset: 0 
    debug: true 

    # The actual plugin constructor 
    Plugin = (element, options) -> 
    this.element = element 
    this.options = $.extend {}, defaults, options 
    this._defaults = defaults 
    this._name = pluginName 
    this.init() 

    Plugin.prototype.init = -> 

    this.bind() 
    this.setHeight() 

    Plugin.prototype.bind = -> 

    # Maintain the scope 
    self = this 

    # Trigger on resize 
    $(window).on 'resize orientationchange', -> 
     self.setHeight() 

    # When scrolling on a touchscreen 
    # prevent further resizes due to address bar shrinking 
    $(window).on 'touchstart', -> 
     self.unbind() 

    Plugin.prototype.getHeight = -> 

    this.log 'Get height from: ', this.options.reference 
    $(this.options.reference).height() 

    Plugin.prototype.setHeight = -> 

    if this.options.offset == parseInt(this.options.offset) 
     offset = this.options.offset 
    else 
     offset = 0 

    $(this.element).css 
     'min-height' : this.getHeight() - offset 

    Plugin.prototype.unbind = -> 

    this.log 'Unbind the resize, touchstart and orientationchange event handlers' 
    $(window).off 'resize touchstart orientationchange' 

    Plugin.prototype.destroy = -> 

    this.unbind() 

    log 'Remove any heights set on', this.element 
    $(this.element).attr('style','') 

    Plugin.prototype.log = (msg, object) -> 
    if this.options.debug 
     if !object 
     object = '' 
     console.log(pluginName + ': ' + msg, object) 

    # A really lightweight plugin wrapper around the constructor, 
    # preventing multiple instantiations 
    $.fn[pluginName] = (options) -> 
    return this.each -> 
     if !$.data(this, 'plugin_' + pluginName) 
     $.data(this, 'plugin_' + pluginName) 
     new Plugin(this, options) 

    return $.fn[pluginName] 

) jQuery, window 

這是生成的JavaScript。它可能是coffeescript環繞函數的匿名函數嗎?

(function(){ 
    (function($, window) { 
     'use strict'; 
     var Plugin, defaults, pluginName; 
     pluginName = 'fullscreen'; 
     defaults = { 
     reference: window, 
     offset: 0, 
     debug: true 
     }; 
     Plugin = function(element, options) { 
     this.element = element; 
     this.options = $.extend({}, defaults, options); 
     this._defaults = defaults; 
     this._name = pluginName; 
     return this.init(); 
     }; 
     Plugin.prototype.init = function() { 
     this.bind(); 
     return this.setHeight(); 
     }; 
     Plugin.prototype.bind = function() { 
     var self; 
     self = this; 
     $(window).on('resize orientationchange', function() { 
      return self.setHeight(); 
     }); 
     return $(window).on('touchstart', function() { 
      return self.unbind(); 
     }); 
     }; 
     Plugin.prototype.getHeight = function() { 
     this.log('Get height from: ', this.options.reference); 
     return $(this.options.reference).height(); 
     }; 
     Plugin.prototype.setHeight = function() { 
     var offset; 
     if (this.options.offset === parseInt(this.options.offset)) { 
      offset = this.options.offset; 
     } else { 
      offset = 0; 
     } 
     return $(this.element).css({ 
      'min-height': this.getHeight() - offset 
     }); 
     }; 
     Plugin.prototype.unbind = function() { 
     this.log('Unbind the resize, touchstart and orientationchange event handlers'); 
     return $(window).off('resize touchstart orientationchange'); 
     }; 
     Plugin.prototype.destroy = function() { 
     this.unbind(); 
     log('Remove any heights set on', this.element); 
     return $(this.element).attr('style', ''); 
     }; 
     Plugin.prototype.log = function(msg, object) { 
     if (this.options.debug) { 
      if (!object) { 
      object = ''; 
      } 
      return console.log(pluginName + ': ' + msg, object); 
     } 
     }; 
     $.fn[pluginName] = function(options) { 
     return this.each(function() { 
      if (!$.data(this, 'plugin_' + pluginName)) { 
      $.data(this, 'plugin_' + pluginName); 
      return new Plugin(this, options); 
      } 
     }); 
     }; 
     return $.fn[pluginName]; 
    })(jQuery, window); 
    }).call(this); 

任何幫助,將不勝感激。

回答

1

你在這裏有一些奇怪的事情發生,所以我會從頂部開始。

CoffeeScript看起來像是將現有的jQuery插件從JavaScript轉換爲CoffeeScript。你應該在CoffeeScript中寫的CoffeeScript:

class Plugin 
    constructor: (@element, options) -> 
    @options = $.extend { }, defaults, options 
    #... 
    @init() 
    init: -> 
    @bind() 
    @setHeight() # The `return` is implicit here 
    bind: -> 
    # Use `=>` instead of an explicit `self = this` trick. 
    $(window).on 'resize orientationchange', => @setHeight() 
    $(window).on 'touchstart', => @unbind() 
    #... 

現在的實際插件定義:

$.fn[pluginName] = (options) -> 
    return this.each -> 
    if !$.data(this, 'plugin_' + pluginName) 
     $.data(this, 'plugin_' + pluginName) 
     new Plugin(this, options) 

if內的$.data call沒有做任何有用的事情,你想要的$.data(obj, key, value)形式的$.data如果你的意圖是將Plugin實例附加到DOM節點。再次,你不需要return S和@在CoffeeScript中比this較爲常見:

$.fn[pluginName] = (options) -> 
    @each -> 
    if !$.data(@, "plugin_#{pluginName}") 
     $.data(@, "plugin_#{pluginName}", new Plugin(@, options)) 

我也切換到串插,而不是+$.data關鍵,這通常更易於閱讀。

現在,你應該能夠說:

$('.js-target').data('plugin_fullscreen').destroy() 

注意,數據關鍵是'plugin_fullscreen'而非'fullscreen'。這當然有點討厭,你可能不想強迫每個人看私人細節。

如果你想要做的jQuery UI的風格之類的東西:

$('.js-target').fullscreen('destroy') 

那麼所有你需要做的是更新的插件功能,要知道,'destroy'應該是一個方法調用,而不是一個options對象。一些簡單的像這應該讓你開始:

$.fn[pluginName] = (args...) -> 
    @each -> 
    plugin = $.data(@, dataKey) 
    if typeof args[0] == 'string' 
     plugin?[args[0]]?() 
    else if !plugin 
     $.data(@, dataKey, new Plugin(@, args[0])) 

所以,如果你說$(x).fullscreen('string')那麼假設你要調用一個方法的內部Plugin例如,所有的運營商存在(?)只是解決失蹤值(插件未附加,未知方法,...);在現實生活中,您可能希望將可以用這種方式調用的方法列入白名單。如果你說$(x).fullscreen(opt: 1)那麼它假設你試圖將插件附加到使用{opt: 1}作爲選項的東西。再一次,這個實際版本可能會更復雜。

Quick'n'dirty演示:http://jsfiddle.net/ambiguous/568SU/1/

你可能想看看jQuery-UI widget factory如果你做了很多這樣的事情,工廠負責了很多不愉快的細節,爲您。

+1

這是一個非常詳細的答案。我很感激你們解釋爲什麼它不起作用,而不是告訴我它應該如何工作。我不熟悉CoffeeScript的細微差別,也不瞭解你提到的巧妙技巧。 – Craig

+0

讓我知道是否有任何技巧(例如'args ...'和'=>'可能)令人困惑,如果您願意,我可以在官方文檔中指出您的位置。我明天下午回來。 –

+0

現在我知道它們存在,我已經在文檔中找到它們。永遠學習!再次感謝。 – Craig