I recently developed a slider with slots, but encountered an issue. The code for this component revolves around the use of IDs for each slide as prop, making it unnecessarily complex. I am convinced that there is a more straightforward way to achieve the same functionality.
<template>
<div class="slider">
<slot class="image"></slot>
<div class="arrow left" @click="prev"
:class="{ 'invisible': !hasPrev() }">
<svg width="80px" height="80px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M13.9783 5.31877L10.7683 8.52877L8.79828 10.4888C7.96828 11.3188 7.96828 12.6688 8.79828 13.4988L13.9783 18.6788C14.6583 19.3588 15.8183 18.8688 15.8183 17.9188V12.3088V6.07877C15.8183 5.11877 14.6583 4.63877 13.9783 5.31877Z" fill="#292D32"></path> </g></svg></div>
<div class="arrow right" @click="next"
:class="{ 'invisible': !hasNext() }"><svg width="80px" height="80px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" transform="rotate(180)"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M13.9783 5.31877L10.7683 8.52877L8.79828 10.4888C7.96828 11.3188 7.96828 12.6688 8.79828 13.4988L13.9783 18.6788C14.6583 19.3588 15.8183 18.8688 15.8183 17.9188V12.3088V6.07877C15.8183 5.11877 14.6583 4.63877 13.9783 5.31877Z" fill="#292D32"></path> </g></svg></div>
</div>
</template>
<script>
import { ref } from "vue";
import { provide } from "vue";
export default {
setup(props, { slots }) {
const carouselIds = ref(slots.default().map((slide) => slide.props.id));
const selectedId = ref(carouselIds.value[0]);
provide("selectedId", selectedId);
return {
carouselIds,
selectedId,
};
},
data(){
return{
id:1
}
},
methods:{
hasNext() {
return this.id < this.carouselIds.length;
},
hasPrev() {
return this.id - 1 >= 1
},
prev() {
if (this.hasPrev()) {
this.selectedId = this.id-=1
}
},
next() {
if (this.hasNext()) {
this.selectedId = this.id+=1;
}
}
},
};
</script>
<style scoped>
.invisible {
visibility: hidden;
}
.slider{
position: relative;
}
.arrow{
cursor: pointer;
display: block;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.arrow.right{
right: 0;
}
.arrow.left{
left: 0;
}
</style>
This Carousel component hosts individual slides within its structure. It creates an array of IDs extracted from props defined in each slide component, allowing for navigation between slides based on their assigned IDs using "next" and "prev" buttons.
<template>
<div class="slide" v-show="id == selectedId">
<slot/>
</div>
</template>
<script>
import { inject } from 'vue';
export default{
props:['id'],
setup(){
const selectedId=inject('selectedId')
return{
selectedId,
}
},
<Carousel>
<Slide id="1">
<img src="https://www.freecodecamp.org/news/content/images/size/w2000/2022/08/Vue-Blog-Cover-2.png">
</Slide>
<Slide id="2">
<img src="https://community-cdn-digitalocean-com.global.ssl.fastly.net/snN3rbgKF7McfuiQAKcoLWMn'">
</Slide >
</Carousel>
I am exploring ways to automatically assign indices to elements in my array and create a new array based on these indices, eliminating the need for explicit IDs. This approach would simplify the process of navigating between slides without manually assigning IDs.
View my code in SFC playground