문제
지금 개발하는 고객 요청이 swiper에서 loop와 한화면에서 slide 개수 1.8개 노출이 있어서 지난번 글 hjh0827.tistory.com/59 에 추가로 해당 옵션을 적용하여 보았다. 그런데 해당 옵션을 적용하면서 vue.js의 특징과 swiper의 option이 문제가 생겼다.
vue.js의 장점은 데이터 렌더링이다. 예전 jsp 시절 화면 진입전에 데이터를 controller에서 조회해서 html에 데이터 기반으로 그린후에 script 영역이 진행되는것이 아닌 html을 그린후에 axios등을 이용하여 데이터를 화면에 렌더링 하는 구조이다.
그런데 여기서 문제가 되는건 vue-awesome-swiper 에서 제공하는 loop option을 쓸때 해당 방식이 문제가 된다.
swiper 공식문서 데모 소스 github.com/nolimits4web/Swiper/blob/master/demos/200-infinite-loop.html 를 기준으로 약간 변경하여 테스트 해보겠다.
swiper 데모
소스
<template>
<swiper class="swiper" :options="swiperOption">
<swiper-slide>a0</swiper-slide>
<swiper-slide>a1</swiper-slide>
<swiper-slide>a2</swiper-slide>
<swiper-slide>a3</swiper-slide>
<swiper-slide>a4</swiper-slide>
<swiper-slide>a5</swiper-slide>
<swiper-slide>a6</swiper-slide>
<swiper-slide>a7</swiper-slide>
<swiper-slide>a8</swiper-slide>
<swiper-slide>a9</swiper-slide>
</swiper>
</template>
<script>
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
// import 'swiper/swiper-bundle.css' // import style (>= Swiper 6.x)
import 'swiper/css/swiper.css' // import style (<= Swiper 5.x)
export default {
components: {
Swiper,
SwiperSlide
},
created(){},
data() {
return {
swiperOption: {
slidesPerView: 1.8, //화면에 slide 노출 개수
slidesPerGroup: 1, //swiper 시 개수
spaceBetween: 10, //간격
centeredSlides: true, //현재 slide 중앙정렬
loop: true, // loop 여부
loopedSlides: 2, //loop 시 duplicate 개수
// autoplay: {
// delay: 1000,
// },
}
};
},
};
</script>
<style lang="scss" scoped>
@import '../assets/css/base.scss';
</style>
html 영역에 이미 swiper-slide가 만들어져있고 swiper에 options으로 data에 선언되어있는 옵션을 setting 해준다. 그러면 데모에서 원하는대로 정상적인 loop swiper가 생성된다.
결과
swiper 실 적용
소스
<template>
<swiper class="swiper" :options="swiperOption">
<swiper-slide v-for="(item,index) in test" :key="index">
{{item.a}}
</swiper-slide>
</swiper>
</template>
<script>
import { Swiper, SwiperSlide } from "vue-awesome-swiper";
// import 'swiper/swiper-bundle.css' // import style (>= Swiper 6.x)
import 'swiper/css/swiper.css' // import style (<= Swiper 5.x)
export default {
components: {
Swiper,
SwiperSlide
},
created(){
setTimeout(() => {
for(let i = 0; i < 9; i++){
this.test.push({a: 'a' + i});
}
}, 3000);
},
data() {
return {
test:[],
swiperOption: {
slidesPerView: 1.8, //화면에 slide 노출 개수
slidesPerGroup: 1, //swiper 시 개수
spaceBetween: 10, //간격
centeredSlides: true, //현재 slide 중앙정렬
loop: true, // loop 여부
loopedSlides: 2, //loop 시 duplicate 개수
// autoplay: {
// delay: 1000,
// },
}
};
},
methods: {},
computed: {}
};
</script>
<style lang="scss" scoped>
@import '../assets/css/base.scss';
</style>
실제 개발시에는 html 에 swiper-slide를 미리 만들어놓을수 없고 axios등 api를 이용하여 데이터를 조회 후 해당 데이터 기반으로 v-for를 이용하여 swiper-slide를 생성를 생성한다.(* api 지연 테스트를 위해 timeout 3초 setting)
결과
swiper 데모에서 제공하는 loop화면과 전혀 다른 화면이 노출된다.
원인 분석
이곳저곳에 구글링해도 slidesPerView 의 개수 수정 및 loop를 함께 쓴 정보가 거의 없어서 찾을수가 없었다. 그래서 예상으론 html에 swiper-slide 가 이미 존재한 상태에서 loop 옵션으로 가장 처음 swiper-slide 앞에 duplicate 를 만들고 가장 마지막 swiper-slide 앞에 duplicate 를 만드는게 일반적이지만 vue.js는 v-for로 이미 loop 옵션이 되어있는 swiper안에 swiper-slide 를 생성하면서 duplicate 생성에 문제가 되는것으로 보인다.
데모 html
<div
class="swiper-wrapper"
style="transition-duration: 0ms; transform: translate3d(-342.222px, 0px, 0px);"
>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate"
data-swiper-slide-index="8"
style="width: 203.889px; margin-right: 10px;"
>
a8
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate swiper-slide-prev"
data-swiper-slide-index="9"
style="width: 203.889px; margin-right: 10px;"
>
a9
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-active"
data-swiper-slide-index="0"
style="width: 203.889px; margin-right: 10px;"
>
a0
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-next"
data-swiper-slide-index="1"
style="width: 203.889px; margin-right: 10px;"
>
a1
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="2"
style="width: 203.889px; margin-right: 10px;"
>
a2
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="3"
style="width: 203.889px; margin-right: 10px;"
>
a3
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="4"
style="width: 203.889px; margin-right: 10px;"
>
a4
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="5"
style="width: 203.889px; margin-right: 10px;"
>
a5
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="6"
style="width: 203.889px; margin-right: 10px;"
>
a6
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="7"
style="width: 203.889px; margin-right: 10px;"
>
a7
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="8"
style="width: 203.889px; margin-right: 10px;"
>
a8
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate-prev"
data-swiper-slide-index="9"
style="width: 203.889px; margin-right: 10px;"
>
a9
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate swiper-slide-duplicate-active"
data-swiper-slide-index="0"
style="width: 203.889px; margin-right: 10px;"
>
a0
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate swiper-slide-duplicate-next"
data-swiper-slide-index="1"
style="width: 203.889px; margin-right: 10px;"
>
a1
</div>
</div>
swiper 데모 소스로 돌렸을때 html 파일이다.
1. 가장 처음 swiper-slide인 a0 앞에 swiper-slide-duplicate 라는 swiper-slide가 2개 생성.
가장 마지막 swiper-slide인 a9 뒤에 swiper-slide-duplicate 라는 swiper-slide가 2개 생성
2. 현재 slide가 a0이므로 swiper-slide-active 추가되었고 앞 slide에 swiper-slide-prev, 뒤 slide에 swiper-slide-next가 class에 추가
3. 현재 slide가 a0이므로 duplicate에 a0에 swiper-slide-duplicate-active가 추가되었고 그 앞 / 뒤로 prev / next가 추가
이런 구조가 swiper 제작자가 원한 구조라고 생각된다.
실 개발 html
<div
class="swiper-wrapper"
style="transition-duration: 0ms; transform: translate3d(85.5556px, 0px, 0px);"
>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate swiper-slide-active"
data-swiper-slide-index="8"
style="width: 203.889px; margin-right: 10px;"
>
a8
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate swiper-slide-next"
data-swiper-slide-index="9"
style="width: 203.889px; margin-right: 10px;"
>
a9
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate-active"
data-swiper-slide-index="0"
style="width: 203.889px; margin-right: 10px;"
>
a0
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate-prev"
data-swiper-slide-index="1"
style="width: 203.889px; margin-right: 10px;"
>
a1
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="2"
style="width: 203.889px; margin-right: 10px;"
>
a2
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="3"
style="width: 203.889px; margin-right: 10px;"
>
a3
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="4"
style="width: 203.889px; margin-right: 10px;"
>
a4
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="5"
style="width: 203.889px; margin-right: 10px;"
>
a5
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="6"
style="width: 203.889px; margin-right: 10px;"
>
a6
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="7"
style="width: 203.889px; margin-right: 10px;"
>
a7
</div>
<div
data-v-fae5bece=""
class="swiper-slide"
data-swiper-slide-index="8"
style="width: 203.889px; margin-right: 10px;"
>
a8
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate-next"
data-swiper-slide-index="9"
style="width: 203.889px; margin-right: 10px;"
>
a9
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate"
data-swiper-slide-index="0"
style="width: 203.889px; margin-right: 10px;"
>
a0
</div>
<div
data-v-fae5bece=""
class="swiper-slide swiper-slide-duplicate swiper-slide-prev"
data-swiper-slide-index="1"
style="width: 203.889px; margin-right: 10px;"
>
a1
</div>
</div>
실 개발 v-for 로 돌렸을때 html 파일이다.
1. 가장 처음 swiper-slide인 a0 앞에 swiper-slide-duplicate 라는 swiper-slide가 2개 생성.
가장 마지막 swiper-slide인 a9 뒤에 swiper-slide-duplicate 라는 swiper-slide가 2개 생성
> 데모 html과 동일
2. 현재 slide가 a8이므로 swiper-slide-active 추가되었고 앞 slide에 swiper-slide-prev, 뒤 slide에 swiper-slide-next가 class에 추가
> 데모 html은 현재 slide가 a0이므로 차이가 생김
3. 현재 slide가 a8인데 swiper-slide-duplicate-active는 a0에 추가. swiper-slide-duplicate-prev는 a1, swiper-slide-duplicate-next는 a9
> 분석 불가
이처럼 swiper-slide-duplicate의 class가 v-for로 생성하면서 문제가 되는것으로 보인다.
해결법
정확한 해결법은 현재 찾지 못한 중.. 1차적인 우회 방법으로는 swiper option에 loopedSlides: 2로 선언하고
swiper.slideTo(2, 1000, false) 을 이용하여 slide 위치를 첫번재로 강제 이동시킨다. slide는 loop에서 생성된 duplicate를 포함하여 이동시키므로 2로 선언하여 사용한다.
'vue.js > vue.js 기능' 카테고리의 다른 글
[vue.js] v-text-field 한글 입력 막기 (4) | 2021.03.10 |
---|---|
vue.js - vue-awesome-swiper loop options 오류 2탄 (2) | 2021.03.03 |
vue.js - vue-roller 사용 및 정리 (1) | 2021.02.11 |
[vue.js] object(객체) 에 없는 데이터 변경 감지 vm.$set (0) | 2021.01.22 |
vue.js - v-model 배열(array)로 데이터 바인딩 하기 (1) | 2021.01.20 |