일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- html
- 개발자
- 프로그래머스코딩테스트
- Redux-Toolkit
- 정보처리기사
- CSS
- 알고리즘스터디
- mysql
- 알고리즘문제
- 프로그래머스
- 프로그래밍
- 프로그래머스 알고리즘
- 코딩테스트
- 자바스크립트
- 코테준비
- 프로그래머스 코딩테스트
- 프로그래머스알고리즘
- 코테공부
- 알고리즘공부
- 1일1코테
- 프로그래머스 레벨0
- next.js 에러
- 프로그래머스코테
- 정처기기출
- 프로그래머스 Lv.0
- 코딩
- js
- 프로그래머스 코테
- 코테스터디
- next.js
- Today
- Total
계발하는 개발자
[Swiper 에러] TypeError: el.removeEventListener is not a function 해결 본문
[Swiper 에러] TypeError: el.removeEventListener is not a function 해결
dev_genie 2023. 9. 22. 18:28에러
원인
여러 상황에서의 테스트 + 나의 개인적인 추론으로는 setSwiper.destroy()로 setSwiper 인스턴스가 존재하는 경우 지웠다가, 아래에서 new Swiper()로 다시 생성할 때 이 과정에서 서로 다른 Swiper 객체가 참조되어 removeEventListener 함수로 지워져서 참조에러가 발생한 게 아닌가 싶다.
// swiper.js
function btSwiper() {
console.log("bt스와이퍼 작동중!")
if (setSwiper) {
// 이미 Swiper 인스턴스가 있으면 제거
setSwiper.destroy();
}
setSwiper = new Swiper('.btSwiper', {
spaceBetween: 20,
slidesPerView: 4,
resistanceRatio: 0, // 드래그시 저항 막기
breakpoints: {
// when window width is >= 900px
900: {
slidesPerView: 4,
},
// when window width is >= 700px
700: {
slidesPerView: 3,
},
// when window width is >= 600px
600: {
slidesPerView: 2,
},
// when window width is >= 300px
300: {
slidesPerView: 1,
}
}
});
}
window.addEventListener('load', btSwiper);
window.addEventListener('resize', btSwiper);
window.addEventListener('beforeunload', function () {
// 페이지 이동시 이벤트 리스너 제거
window.removeEventListener('load', btSwiper);
window.removeEventListener('resize', btSwiper);
});
해결
실제로 위 추론에 맞게 아래 부분 코드를 지우니까 더 이상의 참조에러는 발생하지 않았다.
if (setSwiper) {
// 이미 Swiper 인스턴스가 있으면 제거
setSwiper.destroy();
}
그러나 좀더 안전하게 동작시키기 위해 이벤트 핸들러(생성/제거) 코드를 컴포넌트 페이지로 옮겼다.
<!-- 메인페이지 best 섹션 템플릿 -->
<script>
// 공통기능함수
import crossMixin from "../../js/common.js";
// 공통 템플릿 데이터
import mainData from "../../js/tempData/mainComp.js";
// 제이쿼리 불러오기
import $ from "jquery";
// 스와이퍼 불러오기
import { btSwiper } from "../../js/swiper.js";
// 더미데이터
import { m_bestData } from "../../js/gdsData/mainData.js";
export default {
name: "BestComp",
mixins: [crossMixin],
template: mainData.bestarea,
data() {
return {
// 외부 더미 데이터
m_bestData: m_bestData,
notelnb: ["#1만원대 특가 신발", "#보부상 가방", "#썸머 슈즈"],
};
},
methods: {
moveDet(pm) {
// 로컬스토리지에 데이터 저장
localStorage.setItem("detnm", pm.name);
// 페이지 이동
this.$router.push({ path: "/product/all/best"}).then(() => {
// 페이지 이동후 store 함수 실행!
this.$store.dispatch("setDet");
});
}
},
mounted() {
// 첫번째 dd에 강제 클릭
$(".mbtit2 > dd:first").addClass("on").siblings().removeClass("on").trigger("click");
const index = $(".mbtit2 > dd:first").index();
this.setNum(index);
// 클릭한 dd에만 on 넣기
$(".mbtit2 > dd").click(function() {
$(this).addClass("on").siblings().removeClass("on");
});
// 스와이퍼 호출
btSwiper();
// DOM 로드 & 리사이즈시 호출!
window.addEventListener('load', btSwiper);
window.addEventListener('resize', btSwiper);
},
// 컴포넌트 소멸 전 실행
beforeUnmount() {
window.removeEventListener('load', btSwiper);
window.removeEventListener('resize', btSwiper);
},
};
</script>
그 결과, 현재까지 어떠한 참조에러도 발생하지 않는다!
배운점
위 기능 구현을 위해 다양한 각도로 버그가 발생하는지 따져보고, 해결을 했다.
load 됐을 때 함수 호출하니까 최초 호출하는 코드는 지웠다가 그러면 다른 페이지-> 현재 페이지로 이동해서 올 때 컴포넌트가 초기화 직전에 화면에 표시되어 버리는 시점 차이가 생겨서 셋팅한 값들이 적용이 안되는 것을 목격했다.(spaceBetween 속성 같은)
그래서 반드시 먼저는 위에서 직접 호출해준 다음에 load 되었을 때 다시 한 번 호출시켜야 한다는 걸 확실히 알게 되었다.
또한, beforeUnmount 훅(컴포넌트 소멸 직전 실행되는 훅)을 처음 써보며 그 역할에 대해 이해하게 되었다.
그리고 위와 같은 배움의 경험들로 한 가지의 기능 구현에도 다각도로 문제가 발생하지는 않는지 따져보고,
효과적인 에러 해결 방법을 고민해보게 된 것은 정말 값진 자산이다.
'❗️Error' 카테고리의 다른 글
dev_genie
@dev_genie
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!