我一直在为一个项目开发一些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);
任何帮助都将不胜感激。
答案 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节点。同样,你不需要Plugin
和return
比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如果你做了很多这类事情,工厂会为你处理很多不愉快的细节。