Carousel - first refactor
Setting the position of all slides
Section titled “Setting the position of all slides”Mit diesem Code haben wir die initiale Position der Slides gesetzt:
const slideWidth = slides[0].getBoundingClientRect().widthslides.forEach((slide, index) => { slide.style.left = slideWidth * index + 'px'})Dieser Code ist nicht deklarativ, sondern imperativ. Wir müssen ihn mühsam durchlesen, um zu verstehen, was er tut. Wenn wir diesen in eine Funktion auslagern (z.B. setSlidePositions), dann versteht man sofort, was der Code macht, ohne ihn durchzulesen. slides muss nicht als Argument übergeben werden, weil es im global scope erreichbar ist.
function setSlidePositions() { const slideWidth = slides[0].getBoundingClientRect().width slides.forEach((slide, index) => { slide.style.left = slideWidth * index + 'px' })}Verwendung von setSlidePositions:
setSlidePositions()The next/previousButton event listener
Section titled “The next/previousButton event listener”Im Code für den nextButton’s EventListener haben wir fünf verschiedene Aufgaben erledigt:
current/nextSlideidentifiziert, Positionierung ermittelt- den nächsten Slide angezeigt
- den Zurück-Button eingeblendet (weil es einen vorhergehenden Slide gibt)
- den Vorwärts-Button versteckt, wenn wir beim letzten Slide sind
- den aktuellen Dot hervorgehoben (mit der Zuweisung von
is-selected)
Die entsprechenden Schritte gelten genauso für den previousButton.
Zwei Teile sind gleich:
- Der Teil zum wechseln der Slides
- Die Hervorhebung für den Dot
Refactoring the part for switching slides
Section titled “Refactoring the part for switching slides”Hier noch einmal die beiden Code-Teile in der Übersicht:
nextButton.addEventListener('click', e => { // ... // Show next slide contents.style.transform = `translateX(-${destination})` currentSlide.classList.remove('is-selected') nextSlide.classList.add('is-selected')})
previousButton.addEventListener('click', e => { // ... // Show previous slide contents.style.transform = `translateX(-${destination})` currentSlide.classList.remove('is-selected') previousSlide.classList.add('is-selected')})Der einzige Unterschied besteht darin, dass is-selected einmal dem nächsten und einmal dem vorhergehenden Slide zugewisen wird. Das lässt sich in eine Funktion switchSlide auslagern. Zuerst kopieren wir mal beide Teile in die Funktion:
function switchSlide() { // Show next slide contents.style.transform = `translateX(-${destination})` currentSlide.classList.remove('is-selected') nextSlide.classList.add('is-selected')
// Show previous slide contents.style.transform = `translateX(-${destination})` currentSlide.classList.remove('is-selected') previousSlide.classList.add('is-selected')}Wir brauchen hier drei Dinge:
- den
currentSlide next/previousSlide- diesen nennen wirtargetSlidedestination, also den Wert, um den die Slides verschoben werden sollen
Diese drei Eigenschaften können wir der Funktion als Argumente mitgeben:
function switchSlide(currentSlide, targetSlide, destination) { contents.style.transform = `translateX(-${destination})` currentSlide.classList.remove('is-selected') targetSlide.classList.add('is-selected')}destination erhalten wir aus dem next/previousSlide, also unserem targetSlide:
previousButton.addEventListener('click', e => { // ... const destination = getComputedStyle(previousSlide).left})
nextButton.addEventListener('click', e => { // ... const destination = getComputedStyle(nextSlide).left})Daher nehmen wir diese Variablendeklaration aus den EventListenern raus und bringen sie in der Funktion unter:
function switchSlide(currentSlide, targetSlide) { const destination = getComputedStyle(targetSlide).left
contents.style.transform = `translateX(-${destination})` currentSlide.classList.remove('is-selected') targetSlide.classList.add('is-selected')}Highlighting dots
Section titled “Highlighting dots”Hier noch einmal die beiden Code-Teile in der Übersicht:
nextButton.addEventListener('click', e => { // ... // Highlight dot const currentDot = dotsContainer.querySelector('.is-selected') const nextDot = currentDot.nextElementSibling currentDot.classList.remove('is-selected') nextDot.classList.add('is-selected')})
previousButton.addEventListener('click', e => { // ... // Highlight dot const currentDot = dotsContainer.querySelector('.is-selected') const previousDot = currentDot.previousElementSibling currentDot.classList.remove('is-selected') previousDot.classList.add('is-selected')})Auch dafür können wir eine Funktion schreiben. Nennen wir sie highlightDot. Zuerst kopieren wir wieder beide Teile rein:
function highlightDot() { // highlight next dot const currentDot = dotsContainer.querySelector('.is-selected') const nextDot = currentDot.nextElementSibling currentDot.classList.remove('is-selected') nextDot.classList.add('is-selected')
// highlight previousDot const currentDot = dotsContainer.querySelector('.is-selected') const previousDot = currentDot.previousElementSibling currentDot.classList.remove('is-selected') previousDot.classList.add('is-selected')}Wir sehen, dass wir zwei Variable brauchen: currentDot und next/previousDot. Der wird wieder zum targetDot. Wir übergeben diese beiden Variable als Argumente an die Funktion:
function highlightDot(currentDot, targetDot) { currentDot.classList.remove('is-selected') targetDot.classList.add('is-selected')}Verwendung:
nextButton.addEventListener('click', e => { // ... const currentDot = dotsContainer.querySelector('is-selected') const nextDot = currentDot.nextElementSibling
highlightDot(currentDot, nextDot)})
previousButton.addEventListener('click', e => { // ... const currentDot = dotsContainer.querySelector('is-selected') const previousDot = currentDot.previousElementSibling
highlightDot(currentDot, previousDot)})