我正在编写一个jquery插件,我一直试图找出如何从中调用当前方法执行的元素。
这是我正在做的基本版本。
我有一些表单输入:
<input class="myInput" id="txtInput1" type="text" />
<input class="myInput" id="txtInput2" type="text" />
<input class="myInput" id="txtInput3" type="text" />
我有这个插件:
(function($) {
$.fn.myplugin=function(options) {
options=$.extend({
opt1: 'val1',
etc: ''
}, options);
function example() {
// 'this' in here is the data-myplugin value of the element that called this method.
// ---------------------------------------------------------
//
// How do I determine which element is calling this method ?
//
// eg: in this example how do I know it is the $('#input2') element ?
//
// ---------------------------------------------------------
}
this.each(function() {
// in this example -- loops through each of the form input elements
// .. manipulate the DOM
}).data('myplugin', {
// .. adds data-myplugin to each of the form elements in the loop with a value that is our plugin object which contains our example() method and options
example: example,
options: options
});
return this;
}
})(jQuery);
我以如下方式实例化插件:
$('.myInput').myplugin();
我这样调用example()插件方法:
$('#input2').data('myplugin').example();
我试图避免将其作为参数传递,例如:
// I don't want to have to do this if I don't have to:
$('#input2').data('myplugin').example('input2');
答案 0 :(得分:1)
不幸的是,由于jQuery基于集合的性质,因此该设计存在很大问题,这恰恰导致了您所遇到的问题(这就是为什么您看不到它使用太多的原因)。考虑一下:
<div id="first" class="a c"></div>
<div id="second" class="b c"></div>
然后输入代码:
$(".a").myplugin({option: 1});
$(".b").myplugin({option: 2});
$(".c").data("myplugin").example();
作者显然打算在与example
匹配的所有元素上使用.c
函数,但是data
函数只会返回 first 的数据对象。这些元素的em>,用option: 1
初始化(这通常是jQuery的访问器的工作方式:在集合中的所有元素上设置集合,仅从集合中的第一个元素获取)。创建可解决此问题的数据对象时,您无能为力。
相反,插件应该假定它将针对各种不同的集合而被调用,并且在每种情况下都应使用该集合中每个元素特有的信息。
要做到这一点,请遵循一种完善的模式,使您的插件既具有初始化程序(接受带有选项的对象),又具有方法 (接受带有命令名的字符串): / p>
$(".a").myplugin({option: 1});
$(".b").myplugin({option: 2});
$(".c").myplugin("example");
现在,在myplugin
内,您可以愉快地遍历".c"
集并使用存储在其中的每个元素的选项,这些选项会有所不同(有些是option: 1
,有些则是是option: 2
)。
这是执行上述操作的简单但完整的示例(请参见注释):
(function($) {
// A map of our methods
var methods = Object.create(null);
// Default options
var defaultOptions = {
color: "red",
fontSize: "16px"
};
// Methods
methods.color = function color(set, args) {
// Loop over the elements, using the options specific to each element
// Return the set for chaining
return set.each(function() {
var info = methodEntry(this);
info.$element.css("color", info.options.color);
});
};
methods.fontSize = function fontSize(set, args) {
return set.each(function() {
var info = methodEntry(this);
info.$element.css("font-size", info.options.fontSize);
});
};
methods.getColor = function getColor(set, args) {
// Getters only access the first element...
var info = methodEntry(set[0]);
// ...and return something other than the set
return info.options.color;
}
// init
function init(set, args) {
return set.data("myplugin", $.extend({}, defaultOptions, args[0]));
}
// plumbing
function methodEntry(element) {
var $element = $(element);
var options = $element.data("myplugin");
if (!options) {
throw new Error("myplugin not initialized for element");
}
return {$element: $element, options: options};
}
// Plugin function
$.fn.myplugin = function(methodName) {
var isMethodCall = typeof methodName === "string";
var args = Array.prototype.slice.call(arguments, isMethodCall ? 1 : 0);
var method = isMethodCall ? methods[methodName] : init;
if (!method) {
throw new Error("myplugin has no method called '" + arg + "'");
}
return method(this, args);
};
})(jQuery);
// Using it
$(".a").myplugin({color: "green"});
$(".b").myplugin({color: "blue", fontSize: "20px"});
$(".c").myplugin("color").myplugin("fontSize"); // Note chainging works
console.log($(".c").myplugin("getColor")); // "green" because the *first* element's setting is green
<div id="first" class="a c">first</div>
<div id="second" class="b c">second</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
或者,您可以使用myplugin()
本身来代替data("myplugin")
做相同的事情:
$(".a").myplugin({option: 1});
$(".b").myplugin({option: 2});
$(".c").myplugin().example();
您将myplugin
通过不带选项的调用来响应,方法是返回一个对象,该对象上带有您的方法,并带有一个引用集以调用该方法:
return {
elements: this,
example: ...
}
然后,这些方法将使用this.elements
来使元素起作用。我不会编写完整的示例,但是如果您喜欢该语法,则可以很容易地对其进行修改。