我为我的网站制作了一个简单的旋转木马,我想把它带到下一步。我想在一个页面上有几个旋转木马,我想打电话给$('.carousel').swapify()
并完成它。
这是我到目前为止所拥有的:
$.fn.swapify = function() {
var $this = $(this);
console.log('this is currently: ' + this.selector);
function advanceSlide() {
$('.swapify li:first-child').appendTo('.swapify');
}
$(this).find('li').click(function() { advanceSlide(); });
}
$(document).ready(function () {
$('.carousel').swapify();
});
当我与旋转木马互动时,他们都会前进。这很明显,但我不确定如何使交互具体化。我尝试过类似的东西:
$('li:first-child', this).appendTo(this);
我仍在开发我的javascript词汇表,而且它很难谷歌。
编辑:我设置了一个小提琴来说明这个问题http://jsfiddle.net/69FM7/1/
答案 0 :(得分:2)
IMSoP的答案可能与您的意图相同,但另一种选择是使用委托事件:
$.fn.swapify = (function() {
function advanceSlide(e) {
var $carousel = $(e.delegateTarget);
$carousel.find('li:first-child').appendTo($carousel);
}
return function swapify() {
this.on("click", "li", advanceSlide);
};
}());
以下是一些关键概念的快速解释:
Immediately Invoked Function Expressions
IIFE为您提供了一种方法,可以为新的变量和函数创建一个稳定的新范围。我们创建一个函数并立即调用它。
(function() {
// new scope here
}());
我们在这里使用一个为advanceSlide
和swapify
函数的单个实例创建一个新范围。
IIFE的返回值是swapify
函数。这个函数是一个闭包 - 它关闭了自由变量advanceSlide
。 “自由”在某种意义上,变量advanceSlide
“与swapify
一起”退出“,当它从函数中返回时 - 它可以自由地超出它的范围。
$.fn
是jQuery的prototype
object的别名。简而言之,这意味着jQuery object的所有实例都可以访问原型定义的函数。
为清楚起见,$("someselector")
将返回jQuery object。我们将IIFE的返回值分配给$.fn.swapify
,这将使jQuery对象充满我们的新功能。
当我们调用我们的swapify
帮助程序时,而不是在每个li
上绑定事件 - 这是.find("li").on(...)
将要做的事情 - 最好将事件绑定在父元素上。 然后让jQuery动态检查事件的target
是否与我们关心的集匹配。
例如,您可能只有少数ul
个元素,但每个元素可能包含数百个li
个元素。我们可以简单地在父节点上附加一个处理程序,而不需要创建处理程序并在每个节点上附加事件。这样可以最大限度地减少需要绑定的事件处理程序的数量。
最后,当调用我们的事件处理程序时,它将传递event object。这将有几个有用的属性,例如target
,currentTarget
和delegatedTarget
。我们使用delegatedTarget
来查找我们最初绑定的根元素,并将其分配给$this
。然后,你的其余逻辑按照你期望的方式工作。
答案 1 :(得分:1)
您可以通过以下方式实现此目的:
$.fn.swapify = function() {
$.each($(this), function(index, element) {
var $this = $(this);
function advanceSlide() {
$this.find('li:first-child').appendTo($this);
}
$this.find('li').click(function() { advanceSlide(); });
});
}
由于$this
表示swapify get bind的特定选择器。
<强> Demo Fiddle 强>
这将解决您的问题。
答案 2 :(得分:1)
当扩展jQuery原型(jQuery.fn
)时,你编写的函数被赋予this
传入的完整jQuery对象,在这种情况下是$('.carousel')
,即类carousel
的所有元素的集合。因此,涉及this
的所有内容都适用于整个集合。
您想要做的事情,以及在这种情况下非常常见的事情,是单独对集合中的每个元素采取行动。为此,您可以使用the .each()
function在每个元素上运行相同的函数。每次运行该函数时,this
都设置为单个DOM元素 - 而不是jQuery对象,这就是您需要使用$(this)
重新包装它的原因。
由于函数有自己的作用域,因此使用var $this = $(this)
可以创建“闭包”,它带有特定元素。因为它是在同一范围内声明的,所以函数advanceSlide
就是这样一个闭包 - 每次运行函数时,都会为$this
和advanceSlide
创建新的变量。
请确保始终使用$this
,因为实际的this
变量在函数运行时与定义时不同。 (点击处理程序会将其设置为单击的元素。)因此,最好使用不同的变量名称,例如$carousel
来记住它引用的对象。
由于advanceSlide
已经是本地函数,因此您不需要另一个function() { }
包装器,只需将其传递给.click()
(或.on()
)调用。< / p>
所以你最终得到的是as demoed in this JSFiddle:
$.fn.swapify = function () {
// Here, `this` is a jQuery collection with multiple elements in
this.each(function () {
// Here, `this` is a single DOM node
// using `var`, we make a variable bound to this scope
// while we're at it, we wrap the DOM node with jQuery
// Rather than $this, I've named the variable something meaningful
var $carousel = $(this);
// Declaring a function in the same scope as our var
// creates a "closure", which can always see the scope it was created in
function advanceSlide() {
// When this runs, it will be in response to a click,
// and jQuery will set `this` to the element clicked on
// Our $carousel variable, however, is carried in the closure,
// so we know it will be the container we want
$carousel.find('li:first-child').appendTo($carousel);
}
// A function in JS is just another kind of object,
// so we can pass in advanceSlide like any variable
$carousel.find('li').on('click', advanceSlide);
});
}
$(document).ready(function () {
$('.swapify').swapify();
});