2

我在页面上有可变数量的滑块。每个滑块包含可变数量的幻灯片,以及一对用于按顺序浏览其各自幻灯片的上一个/下一个按钮。

这是典型滑块的标记:

<section class="foo">
    <button class="prev"></button>

    <ul class="container slider">
        <li class="slide" id="a01"></li>
        <li class="slide" id="a02"></li>
        <li class="slide" id="a03"></li>
    </ul>

    <button class="next"></button>
</section>

每个滑块都应该知道它当前显示的幻灯片的索引。这让我相信在页面加载时,我应该遍历所有$('.slider')元素并为每个元素实例化一个对象。如何编写定义滑块的类?它应该有一个包含当前显示的幻灯片的索引的属性,以及一个根据用户单击“下一个”还是“上一个”来增加或减少该属性的方法。我已经做到了:

var slider = function () {
    this.pager = 0;
    this.incrementPager = function () {
        console.log(this.pager++);      
    };
};

$(function () {
    $('.prev, .next').click(slider);
});

...但我的代码并没有做太多:)

4

3 回答 3

4

这是制作 jQuery 插件的方法,我认为这是一种更好的方法,因为您使用的是 jQuery,这并不真正适用于基于的 OO。

$.fn.slider = function() {
    $(this).each(function() {
        var wrapper = $(this);
        var index = 0;
        var listItems = wrapper.find('.slide');
        wrapper.find('.prev').click(function(){
            if (index > 0) {
                $(listItems[index]).removeClass('active');
                index--;
                $(listItems[index]).addClass('active');
            }
        });
        wrapper.find('.next').click(function(){
            if (index < listItems.length - 1) {
                $(listItems[index]).removeClass('active');
                index++;
                $(listItems[index]).addClass('active');
            }
        });

    });
};

你可以像这样使用它

$('section').slider();

工作示例 http://jsfiddle.net/MR8wE/

如果你真的想要一些 OO,你可以执行以下操作(但我认为这与 jQuery 的工作方式背道而驰)。

/**
 * Adds behavior to the HTML for a slider
 */
function Slider(wrapper) {
    var me = this;
    me.wrapper = $(wrapper);
    me.index = 0;
    me.listItems = wrapper.find('.slide');
    wrapper.find('.prev').click(function(){
        me.prev(); 
    });
    wrapper.find('.next').click(function(){
        me.next();
    });                    
}

Slider.prototype.next = function() {
    this.go(1;)
}
Slider.prototype.previous = function() {
   this.go(-1);
}
Slider.prototype.go = function(steps) {
    var oldIndex = this.index;
    var newIndex =  oldIndex + steps
    if (newIndex >= 0 && newIndex < this.listItems.length ) {
        $(this.listItems[oldIndex]).removeClass('active');
        $(listItems[new]).addClass('active');
        this.index = newIndex;
    }

}

然后你会像使用它一样

var sliders = [];
$('section').each(function(){
     sliders.push(new Slider(this));        
});

// Control the slider without user intervention
sliders[0].next();
sliders[1].go(2);

示例http://jsfiddle.net/MR8wE/2/

于 2012-10-10T16:16:05.683 回答
2

针对评论中的问题:

function Slider(elm)
{
    this.domElement = elm;
    this.pager = 0;
}
Slider.prototype.incrementPager = function()
{
    this.pager++;
};//all instances share this method ==> only 1 function object in mem.
$(function()
{
    var objectCollection = (function(elements)
    {
        var toReturn = [];
        var scanElementsFunction = function()
        {//declared in this scope, to have access to elements var
            'use strict';//avoid setting globals
             if (this.allElems === undefined)
             {
                 this.allElems = elements;
             }
             return this.allElems;
        };
        elements.each(function(idx,el)
        {
            toReturn[idx] = new Slider(el);//<-- pass DOMElement to constructor
            toReturn[idx].getAll = scanElementsFunction;//<-- reference, no new function object
        });
        return toReturn;
    }($('.prev, .next')));//this scope preserves the elements returned by jQuery selector
    console.log(objectCollection);
});

那里没有什么真正有用的东西,但我试图在保持片段尽可能短的同时加入尽可能多的技巧和技巧。如果某些代码不清楚,请告诉我,我会提供更多解释(可能需要一两个小时,因为我现在要咬一口 :))

于 2012-10-10T15:59:51.033 回答
2

以下方法使用更正式的构造函数和原型,使其保持轻量级,而不是堆叠外壳。构造函数是...

function Slider(slides, transition) {

    // Keeps a reference to the current slide index
    this._current = 0;

    // An array of slides
    this._slides = slides;

    // A transition function
    this._transition = transition;
}

它接受一个幻灯片数组和一个函数,当我们在它们之间转换时将给出两张幻灯片。这意味着我们通过外部化来控制我们的过渡效果。它也与框架无关,并且不依赖于 jQuery 或任何其他框架。构造函数本身并没有做太多事情。下面的方法就是我们的肉...

// The function that swaps slides
Slider.prototype.goto = function(i) {

    // Do a bit of sense checking
    if(i > this._slides.length || i < 0)
        throw new Error("Slide does not exist");

    // Swap the slides by passing them to the transition function
    var currentSlide = this._slides[this._current];
    var nextSlide = this._slides[i];
    this._transition(currentSlide, nextSlide);

    // Update the current index
    this._current = i;
};

它获取幻灯片的新索引并将旧幻灯片和新幻灯片传递给过渡功能。然后它会更新用于跟踪当前幻灯片的索引。然后我们想要实现一个旋转的上一个和下一个函数,所以下面的方法描述了我们如何使用模数来做到这一点,注意我们必须添加幻灯片的长度,因为负模数不能按照我们想要的方式工作。

// Calculate the next index as a rotating index
Slider.prototype.getNextIndex = function() {
    return (this._current + 1) % this._slides.length;
};

// Calculate the previous index as a rotating index
Slider.prototype.getPrevIndex = function() {
    return (this._current + this._slides.length - 1) % this._slides.length;
};

然后我们加点糖...

// Sugar to go next and prev
Slider.prototype.next = function() {
    this.goto(this.getNextIndex());
};
Slider.prototype.prev = function() {
    this.goto(this.getPrevIndex());
};

您可能无法将 prev 和 next 按钮与其滑块关联起来。您可以在滑块元素之前和之后找到它们,或者像我在下面所做的那样将它们包含在滑块元素中。要使用 jQuery 设置滑块,您可以执行以下操作...

$(".slider").each(function() {
    var slider = new Slider($(this).find(".slide"), function(a, b) {
        $(a).hide();
        $(b).show();
    });
    $(this).data("slider", slider);
    $(this).find(".prev").click(function() {
        slider.prev();
    });
    $(this).find(".next").click(function() {
        slider.next();
    });
});

编辑这是在行动http://jsfiddle.net/w8u69/

而且由于转换的逻辑是公开的,您可以很容易地添加转换效果,而无需修改原始Slider“类”。http://jsfiddle.net/w8u69/1/

编辑只是为了展示这种方法的强大功能,无需修改原始滑块“类”,您可以添加额外的逻辑以在幻灯片之间自动移动。您可以使用装饰器或继承来完成此操作,但此示例显示了如何使用组合来完成。http://jsfiddle.net/w8u69/4/

最后一件事,这可能是纯 OO 方法中最重要的一点,通过简单地更改集成代码并保持 OO“类”不变,我们可以重用我们为滑块编写的逻辑并将其插入一个完全不同的框架。这个小提琴显示它与 MooTools http://jsfiddle.net/w8u69/5/一起使用

于 2012-10-10T16:18:57.850 回答