ES6 类,同一页面上的两个滑块具有相同的选择器类

ES6 classes, two sliders on same page with same selector class

提问人:jerome vermenot 提问时间:10/28/2023 最后编辑:jerome vermenot 更新时间:10/28/2023 访问量:47

问:

我正在重构一个脚本,其中我正在构建一个滑块。在同一页面中,我希望能够显示两个具有相同类的滑块来选择它们 (.slider)。我设法初始化了两个滑块,但只有页面上的第二个滑块有效。当我单击第一个滑块中的箭头时,它会作用于页面上的第二个滑块...... 谢谢大家!

JS系列

export default class Slider {
    sliders: NodeListOf<HTMLElement> | null = null;
    slides!: HTMLElement;
    current: Element | undefined;
    caption!: HTMLElement;
    prev: Element | undefined;
    next: Element | undefined;

    constructor() {
        this.sliders = document.querySelectorAll('.slider');

        if (this.sliders.length) {
            this.sliders.forEach((slider: HTMLElement) => {
                this.slides = slider.querySelector(
                    '.slider__inner'
                ) as HTMLElement;
                let prevButton = slider.querySelector(
                    '.slider__controls-prev'
                ) as HTMLSpanElement;
                let nextButton = slider.querySelector(
                    '.slider__controls-next'
                ) as HTMLSpanElement;

                prevButton.addEventListener('click', () => this.move('prev'));
                nextButton.addEventListener('click', () => this.move());
                console.log(prevButton, nextButton);

                this.init(slider);
                this.applyClasses();
                this.setCaption();
            });
        }       
    }

    init(slider: HTMLElement): void {
        this.current =
            slider.querySelector('.slider__item-current') ||
            (this.slides.firstElementChild as HTMLLIElement);
        this.caption = slider.querySelector(
            '.slider__item-caption'
        ) as HTMLElement;
        this.prev =
            this.current.previousElementSibling ||
            (this.slides.lastElementChild as HTMLLIElement);
        this.next =
            this.current.nextElementSibling ||
            (this.slides.firstElementChild as HTMLLIElement);
    }

    applyClasses(): void {
        this.current?.classList.add('slider__item-current');
        this.prev?.classList.add('slider__item-prev');
        this.next?.classList.add('slider__item-next');
    }

    setCaption(): void {
        this.caption.textContent = this.current?.querySelector('figcaption')?.textContent;
    }

    move(direction?: string): void {
        const classesToRemove: string[] = [
            'slider__item-prev',
            'slider__item-current',
            'slider__item-next',
        ];
        this.prev?.classList.remove(...classesToRemove);
        this.current?.classList.remove(...classesToRemove);
        this.next?.classList.remove(...classesToRemove);

        if (direction === 'prev') {
            [this.prev, this.current, this.next] = [
                this.prev?.previousElementSibling ||
                    (this.slides.lastElementChild as HTMLElement),
                this.prev,
                this.current,
            ];
        } else {
            [this.prev, this.current, this.next] = [
                this.current,
                this.next,
                this.next?.nextElementSibling ||
                    (this.slides.firstElementChild as HTMLElement),
            ];
        }

        this.applyClasses();
        this.setCaption();
    }
}

HTML(智能模板)

<div class="slider">
            <div class="slider__wrapper">
                <ul class="slider__inner">
                    {{foreach from=$element.diaporama.images item="diapo"}}
                        <li class="slider__item">
                            <figure>
                                {{if $diapo.texte != ""}}
                                    {{assign var=alt value=$diapo.texte|html}}
                                {{/if}}
                                {{if $diapo.author != ""}}
                                    {{assign var=auteur value=$diapo.author|html}}
                                    {{assign var=alt value="`$alt` ©`$auteur`"}}
                                {{/if}}
                                <img loading="lazy" 
                                srcset="{{$diapo.url|image_bunny:cw480}} 480w,
                                        {{$diapo.url|image_bunny:cw600}} 600w,
                                        {{$diapo.url|image_bunny:cw1204}} 1204w"
                                sizes="(min-width: 767px) 600px,
                                    (min-width: 1184px) 1204px,
                                    480px" 
                                src="{{$diapo.url|image_bunny:cw480}}" alt="{{$alt|utf2asc|html_entity_decode|html}}">
                                <figcaption>
                                    {{if $diapo.texte != ""}}
                                        {{$diapo.texte|replace:"<p>":""|replace:"</p>":""}}
                                    {{else}}
                                        {{$diapo.titre|replace:"<p>":""|replace:"</p>":""}}
                                    {{/if}}
                                    {{if $auteur != ""}}
                                        <span>&copy {{$auteur}}</span>
                                    {{/if}}
                                </figcaption>
                            </figure>
                        </li>
                    {{/foreach}}
                </ul>
                <div class="slider__controls">
                    <span class="slider__controls-prev picto-chevron"></span>
                    <span class="slider__controls-next picto-chevron"></span>
                </div>
            </div>
            <div class="slider__item-caption"></div>
        </div>
JavaScript TypeScript

评论

0赞 Bergi 10/29/2023
我希望一个类负责每个实例的一个滑块。它不应该处理页面上的所有滑块。如果有多个滑块,则应多次实例化它。Slider

答:

0赞 Nkemdi Anyiam 10/28/2023 #1

这是构造函数中的简单逻辑错误。您的循环第一次运行并设置了一堆字段,并运行了一些方法,为第一个滑块设置了更多内容,对吗?但是,一旦该循环第二次运行,它就会使用第二个滑块重新分配所有这些内容。例如,当它运行时,只是被更改为第二个滑块的,因此第一个滑块就没有了。forEach()this.<blablabla>thisinit()this.currentquerySelector('.slider__item-current')

您只需要找到一种方法来设置所有内容,而不会让滑块的数据相互覆盖。

评论

0赞 jerome vermenot 10/29/2023
感谢您的回复@NkemdiAnyiam我试图将我的价值观彼此独立地隔离开来,但我不知道该怎么做......