我正在为我的网站编写简单的滑块。此滑块包含列表项。我想使用OOP方法。
我的实际代码:
var miniSlider = function(objId)
{
this.obj = $("#" + objId);
this.obj.settings = [];
this.obj.settings['items'] = $('ul li', this.obj).length;
this.pagerNext = this.obj.find("i.next");
this.pagerPrev = this.obj.find("i.prev");
this.pagerNext.on("click", function() {
alert(this.obj.settings['items']);
});
};
我可以调用其他一些滑块(是的,这就是我引入类的原因):
miniSlider("mini-slider");
问题是,当我在jQuery this.pagerNext.on("click",function(){})中时这个不再是我的对象,而是变成了一个点击的元素。如何在点击后以良好的方式访问此.obj.settings(并支持多滑块)?
编辑:
以下是与SOF社区合作创建的完整代码:)
var MiniSlider = function(objId)
{
this.obj = $("#" + objId);
this.obj.settings = {
items: $("ul li", this.obj).length,
autoChangeTime: 8000
};
this.obj.activeElement = null;
this.pagerNext = this.obj.find("i.next");
this.pagerPrev = this.obj.find("i.prev");
var self = this;
this.pagerNext.on("click", function() {
self.obj.activeElement = $('li.active', self.obj);
if(self.obj.settings.items > 0)
{
if(self.obj.activeElement.is(':last-child'))
{
$('li.active', self.obj).removeClass('active');
$('li', self.obj).first().addClass('active');
}
else
{
self.obj.activeElement.next().addClass('active').prev().removeClass('active');
}
}
});
this.pagerPrev.on("click", function()
{
self.obj.activeElement = $('li.active', self.obj);
if(self.obj.settings.items > 0)
{
if(self.obj.activeElement.is(':first-child'))
{
self.obj.activeElement.removeClass('active');
$('li', self.obj).last().addClass('active');
}
else
{
self.obj.activeElement.prev().addClass('active').next().removeClass('active');
}
}
});
this.obj.parent().on('mouseenter mouseleave', function(e) {
if (e.type == 'mouseenter')
{
$(this).addClass('stop');
}
else
{
$(this).removeClass('stop');
}
});
setInterval(function() {
if(self.obj.settings.items > 0 && !self.obj.parent().hasClass("stop"))
{
self.pagerNext.click();
}
}, this.obj.settings.autoChangeTime);
};
并调用:
new MiniSlider("mini-slider");
Alex在回调中为您提供了this
问题的解决方案,但您的代码中还有另一个问题。
您正在调用没有new
运算符的miniSlider()
函数:
miniSlider("mini-slider");
这意味着在函数内部,this
不是唯一的对象,而是window
对象!
您需要使用new
运算符为每个调用创建一个单独的对象:
new miniSlider("mini-slider");
但您也应该更改此函数的名称,以遵循构造函数以大写字母开头的JavaScript约定。称之为MiniSlider
,并像这样使用:
new MiniSlider("mini-slider");
如果您遵循这个约定(大多数有经验的JavaScript程序员都这样做),它将帮助您记住何时使用new
。如果函数以大写字母开头,则它是一个构造函数,需要使用new
。否则,则不需要。
如果您希望能够在不使用new
的情况下使用构造函数,那么也可以使用更多的代码,例如:
function MiniSlider( objId ) {
if( this == window ) return new MiniSlider( objId );
// the rest of your constructor code goes here
}
但通常情况下,人们并不在意这一点,只是使用构造函数上的首字母大写来提醒使用new
。
此外,作为一个建议,当我在变量中保存this
时,我喜欢使用一个有意义的名称,然后我会一致地使用该名称,而不是使用this
。这样做可能看起来像:
var miniSlider = function(objId) {
var slider = this;
slider.obj = $("#" + objId);
slider.obj.settings = [];
slider.obj.settings['items'] = $('ul li', slider.obj).length;
slider.pagerNext = slider.obj.find("i.next");
slider.pagerPrev = slider.obj.find("i.prev");
slider.pagerNext.on("click", function() {
alert(slider.obj.settings['items']);
});
};
为什么我更喜欢这种方法,而不是在大多数地方使用this
,在需要的地方使用另一个变量self
?这样,我就不必记住该使用哪个了:我可以始终在代码中使用slider
而不是this
。(当然,你可以使用self
或任何其他名称;如果我要编一个名字,我只想有一个更有意义的名称。)
代码中的另一个小问题是这两条语句:
slider.obj.settings = [];
slider.obj.settings['items'] = $('ul li', slider.obj).length;
当你要给它这样的命名属性时,你不应该使用Array
。请改用Object
。只有当你有0、1、2等数字索引时,才应该使用数组。使用对象文字,你可以同时设置属性:
slider.obj.settings = {
items: $('ul li', slider.obj).length
};
此外,当您使用该属性时:
alert(slider.obj.settings['items']);
你可以更简单地写为:
alert(slider.obj.settings.items);
无论哪种方式,它都会做同样的事情。
在本地变量中保存对此的引用,并在嵌套函数中使用该变量而不是this
。
var self = this;
this.pagerNext.on("click", function() {
alert(self.obj.settings['items']);
});