컴포넌트내에 스크롤 이벤트 감지 로직 - ChoDragon9/posts GitHub Wiki
헤더와 푸터 컴포넌트의 스크롤 이벤트 감지
추상화 대상은 무엇?
추상화 전략은 무엇?
근거는?
결론
배경 설명
컴포넌트의 요구사항은 이렇다.
- [헤더] 스크롤 시, 태그에 scroll 클래스 추가
- [푸터] 스크롤 시, Top 버튼 노출
요구 사항은 다르지만 스크롤이라는 동작을 감지해야 한다. 헤더와 푸터의 부모 컴포넌트에서 스크롤을 감지 할수 있지만 헤더와 푸터는 2가지의 레이아웃 컴포넌트에서 사용되고 있다.
content-layout.vue
├─ page-header.vue
├─ contents.vue
└─ page-footer.vue
project-layout.vue
├─ page-header.vue
├─ alarm.vue
└─ page-footer.vue
중복되는 로직은 이런 형태이다. 두 클래스의 중복은 상수, 함수, 라이프 사이클 훅 부분이 중복된다. 요구사항은 다른 시점에 추가되었으며 의도적으로 네이밍도 동일하게 중복되게 구현했다. 이유는 중복되었음을 쉽게 식별할 수 있기 때문이다.
class PageHeader extends Vue {
readonly SCROLL_EVENT = 'scroll'
readonly SCROLL_LIMIT = 10
isScrolling = ToggleHelper.create()
handleScroll(): void {
if (window.scrollY > this.SCROLL_LIMIT) {
this.isScrolling.on()
} else {
this.isScrolling.off()
}
}
mounted(): void {
window.addEventListener(this.SCROLL_EVENT, this.handleScroll)
}
beforeDestroy(): void {
window.removeEventListener(this.SCROLL_EVENT, this.handleScroll)
}
}
class PageFooter extends Vue {
readonly SCROLL_EVENT = 'scroll'
readonly SCROLL_LIMIT = 10
topButton = ToggleHelper.create()
handleScroll(): void {
if (window.scrollY > this.SCROLL_LIMIT) {
this.topButton.on()
} else {
this.topButton.off()
}
}
mounted(): void {
window.addEventListener(this.SCROLL_EVENT, this.handleScroll)
}
beforeDestroy(): void {
window.removeEventListener(this.SCROLL_EVENT, this.handleScroll)
}
}
고려사항
- 컴포넌트를 사용할 때만 스크롤 이벤트를 감지해야 한다.
- 컴포넌트의 생명주기와 스크롤 감지가 같아야 한다.
- 상태와 로직의 중복이기 때문에 클래스를 통해 해결한다.
해결방안
스크롤 이벤트를 감지하는 클래스를 만들어 해결
export class ScrollDetector {
readonly SCROLL_EVENT = 'scroll'
readonly SCROLL_LIMIT = 10
private toggleDetection = ToggleHelper.create()
get isScrolled(): boolean {
return this.toggleDetection.isOn
}
private handleScroll = (): void => {
window.scrollY > this.SCROLL_LIMIT
? this.toggleDetection.on()
: this.toggleDetection.off()
}
start(): void {
window.addEventListener(this.SCROLL_EVENT, this.handleScroll)
}
stop(): void {
window.removeEventListener(this.SCROLL_EVENT, this.handleScroll)
}
static create(): ScrollDetector {
return new ScrollDetector()
}
}