OOJS的问题

时间:2012-10-10 15:19:30

标签: javascript jquery oop

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

以下是典型滑块的标记:

<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);
});

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

3 个答案:

答案 0 :(得分:4)

以下是如何创建一个jQuery插件,我认为这是一种更好的方法,因为你使用的是jQuery,它实际上并不适用于基于 Class 的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/

答案 1 :(得分: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);
});

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

答案 2 :(得分: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;
};

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

// 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/