无法破坏jQuery插件

时间:2014-07-27 03:18:44

标签: jquery jquery-plugins coffeescript destroy

我一直在为一个项目开发一些javascript,并认为它应该是一个jQuery插件。我以前写过一些,但这需要更强大和可破坏。为此,我已经学习了一些教程,但在描述如何破坏插件时,它们都达不到。

那么如何销毁插件呢?我似乎无法访问$('.js-target).fullscreen('destroy')似乎无法正常工作。 $(.js-target).data('fullscreen').destroy()也不会在控制台中返回TypeError: Cannot read property 'destroy' of undefined

我用coffeescript写的。生成的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 个答案:

答案 0 :(得分: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并没有做任何有用的事情,如果你的目的是附加{{1},你需要$.data(obj, key, value)形式的$.data实例到DOM节点。同样,你不需要Pluginreturn比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'。当然这有点令人讨厌,你可能不想强迫每个人查看私人信息。

如果你想做jQuery-UI风格的事情,比如:

'fullscreen'

然后您需要做的就是更新插件函数以了解$('.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)作为选项的内容中。再一次,这个真实版本可能会更复杂。

快速的肮脏演示:http://jsfiddle.net/ambiguous/568SU/1/

你可能想看看jQuery-UI widget factory如果你做了很多这类事情,工厂会为你处理很多不愉快的细节。