
프로젝트를 진행하는 중 swiper를 사용해서 슬라이드를 구현하는 부분이 있었다.
이 부분은 loop 기능을 추가해서 무한으로 옆으로 넘길 수 있는 형태이다.

<div ref="swiperRef">
<swiper
v-if="productList?.length"
:options="swiperOption">
<swiper-slide
v-for="(product, idx) in productList"
:key="idx">
<custom-component/>
</swiper-slide>
</swiper>
</div>
const swiperOption: SwiperOptions = {
simulateTouch: true,
navigation: {
nextEl: '.home-top-next-btn',
prevEl: '.home-top-prev-btn',
},
autoplay: { disableOnInteraction: false, delay: 2000 },
loop: true,
centeredSlides: true,
slidesPerView: 'auto',
spaceBetween: 8,
touchStartPreventDefault: false,
speed: 600,
on: {
init(this) {
swiperRef.value = this as SwiperComponent;
setObserveRef(this);
},
click(this, event) {
const target = event?.target;
if (!(target instanceof HTMLElement)) return;
if (!swiperRef.value || !swiperRef.value.clickedSlide) return;
const clickedSlide = swiperRef.value.clickedSlide;
const clickedSlideIdx = clickedSlide.dataset.swiperSlideIndex;
const isClickStore = target.closest('.new-trend-insights-store');
const isClickGoods = target.closest('.new-trend-insights-goods');
const goods = productList.value?.[Number(clickedSlideIdx)];
if (!clickedSlideIdx || !goods) return;
if (isClickStore) {
//store 이미지를 클릭했을 때 실행되는 액션
} else if (isClickGoods) {
// 상품 이미지를 클릭했을 때 실행되는 액션
}
},
slideChange(this) {
swiperRef.value = this as SwiperComponent;
},
},
threshold: 5,
};
swiperOption 에서 click 이벤트를 정의한다.
상품 이미지 카드에 class로 .new-trend-insights-goods 를 주고
스토어 이미지 카드에 class로 .new-trend-insights-store 를 준다.
(포인트는 다른 클래스명을 준다는 뜻)
클릭 이벤트가 발생했을 때 target.closet 으로 클릭된 요소를 찾아서
클릭이 발생한 요소에 해당하는 액션을 정의한다.
이렇게 하면 각각에 이벤트를 줄 수 있다!
swiper에 호버를 했을 시 양옆 페이지네이션 버튼의 bg를 넣어주고 호버하지 않았을 시에는 bg를 빼는 코드가 있었다.
const isHovered = ref(false);
<div
ref="swiperRef"
@mouseenter="onMouseEnter"
@mouseleave="onMouseLeave">
<swiper 관련 코드 .../>
<button
class="home-top-prev-btn absolute left-[40px] top-[50%] z-[1] translate-y-[-50%] p-[12px]"
:class="{ 'bg-black-020': isHovered }">
...
</button>
<button
class="home-top-next-btn absolute right-[40px] top-[50%] z-[1] translate-y-[-50%] p-[12px]"
:class="{ 'bg-black-020': isHovered }">
...
</button>
</div>
기존에는 mouseEnter, mouseLeave 이벤트가 발생할 때 마다 isHovered값을 변경해주고 그 변경된 값을 가지고 tailwind class를 동적으로 넣어주고 있었다. 이 state가 바뀔 때 마다 button만 리렌더링되는 게 아니라 swiper 도 리렌더링되었다.
그래서 해결은 state를 사용하지 않고 tailwind의 group을 사용해서 css 만 변경시켜주는 것으로 수정했다. tailwind를 사용하지 않는다면 element를 직접 선택해서 스타일을 바꿔주는 것과 동일하다.
<div
ref="swiperRef"
class="group"
@mouseenter="onMouseEnter"
@mouseleave="onMouseLeave">
<swiper 관련 코드 .../>
<button
class="home-top-prev-btn group-hover:bg-black-020 absolute left-[40px] top-[50%] z-[1] translate-y-[-50%] p-[12px]"
:class="{ 'bg-black-020': isHovered }">
...
</button>
<button
class="home-top-next-btn group-hover:bg-black-020 absolute right-[40px] top-[50%] z-[1] translate-y-[-50%] p-[12px]"
:class="{ 'bg-black-020': isHovered }">
...
</button>
</div>
group 클래스를 설정한 태그에 hover, focus, active 이벤트가 발생했을 때 자식요소의 class를 바꿀 수 있다.
위의 코드에서 보면 div에 group클래스가 있고
자식인 button에 group-hover:bg-black-020 클래스가 있다.
div에 hover 이벤트가 발생하면 자식인 button에 bg클래스를 준다는 뜻!
라이브러리를 사용한다고 해서 꼭 라이브러리에 있는 기능이 아니더라도 기존 지식을 활용해서 창의적으로 문제 해결 방법을 찾아야 한다.