我正在第一次编写 JQuery 插件 - 几乎已经完成 - 并试图找到最好的“样板”来满足以下需求。
这是我的问题:
我无法让插件通过类名来处理元素。
这有效:
var myPlugin = $('#single').myPlugin(); // Yes - it gets initialised
myPlugin.doAFunction(" Some Params "); // Yes - public access func works
这不起作用:
var myPluginFooClass = $('.foo').myPlugin(); // Yes, it gets initialised
myPlugin.doAFunction(" Some Params "); // NO - now this falls over
这是我需要实现的目标:
- 同一页面上有多个实例
- 每个实例都有自己的变量,这些变量在部署时不会被其他实例覆盖(我使用的是 $.data)
- 公共(public)访问函数仅影响该实例,而不影响其他实例!
- 实例可以通过其 id (#myElement) 部署在单个元素上
- 实例可以按类(.foo)部署在元素上 - 这是行不通的
这是我的 JQUERY 代码:
(function($){
$.fn.myPlugin = function(options) {
// support multiple elements
if (this.length > 1){
this.each(function() { $(this).myPlugin(options) });
return this;
}
// -- private variables --
var $this = $(this);
// default settings
var defaults = {
initialText: 'I have been initialized'
};
// Merge defaults with setup options
var options = $.extend({}, defaults, options);
// Protect final options, placing inside jQuery element data
$this.data('myPlugSettings', options);
// Shortcut var to access option data
var settings = $this.data('myPlugSettings');
// private methods
var fooPrivate = function() {
// do something private ...
};
// public methods
this.changeText = function(param) {
$this.text(param);
};
// Constructor
this.init = function() {
$this.text( settings.initialText );
// Return this for chainability?
return this;
};
return this.init();
}
})(jQuery);
// globals
_ = {
myPlugin: null,
myPluginTwo: null,
myPluginFoo: null
}
// Button Event handlers
$("#btnLoadPlugs").click(function(e) {
_.myPlugin = $('#single').myPlugin({
initialText: "Custom initial text"
});
_.myPluginTwo = $('#anotherSingle').myPlugin();
_.myPluginFoo = $('.foo').myPlugin();
});
$("#btnGoSingle").click(function(e) {
_.myPlugin.changeText(" Worked on single ID ");
});
$("#btnGoAnotherSingle").click(function(e) {
_.myPluginTwo.changeText(" Worked again here ");
});
$("#btnGoFoo").click(function(e) {
// THIS FALLS OVER ???????????
_.myPluginFoo.changeText(" foos get this ");
});
My JS Fiddle这里让这个问题很容易理解。
最佳答案
TLDR
_.myPluginFoo
使用 changeText
方法释放对 jQuery 对象的引用。
// support multiple elements
if (this.length > 1){
this.each(function() { $(this).myPlugin(options) });
// Send the collection back.
return this;
}
只是为了让它发挥作用
// This will work, but this is not exactly what you have intended.
_.myPluginFoo.each(function(key, value) {
$(value).myPlugin().changeText('Hello');
});
为什么?
这是 Sizzle 选择器引擎的预期行为,$('#unique')
调用将返回带有单个 HTMLElement 的 jQuery Collection 实例,可通过$('#unique')[0]
。
通过将 $.fn.myPlugin
中的 $('#unique')
修改为 this
,您将获得一个带有 changeThext
属性。
$('.foo').myPlugin()
的结果是 this.length > 1//true
通过调试以下代码,您将轻松注意到差异:
$("#btnLoadPlugs").click(function(e) {
// ...
console.log(_.myPluginTwo); // Single object.
console.log(_.myPluginFoo); // A collection, without changeText method.
});
您使用的 $.data
保护不是很有效。
更好的方法
如果有意义的话,您还可以实现类似 $('.foo').myPlugin('changeText', 'new text')
的内容。
看看jQuery Boilerplate ,这是 jQuery 插件最好的事情之一。
关于javascript - JQuery插件,多个实例同一页面;适用于元素类和唯一元素 ID;用 $.data 保护选项;公共(public)访问功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31482718/