propro프로젝트에서도 고민했던 문제였는데 컴포넌트로 추상화하여 구현하였던 프로젝트에서 부모 컴포넌트에 의해 자식 컴포넌트가 여러번 재생성되었을 때 이벤트가 핸들러가 중복적으로 붙여지는 문제가 발생하였다.
대표적으로 window.addEventListener(type, listener)
를 사용해서 특정 요소의 바깥 범위를 클릭한 경우를 감지하기 위해 활용했던 이벤트에서 발생했는데 원인은 매번 컴포넌트가 생성될 때 이벤트 리스너를 등록해주기 때문이었다.
그렇다면 중복적인 이벤트 리스너 등록문제를 해결하기 위해서는 리스너를 등록하기 전에 기존의 이벤트를 제거해줘야 하는 과정이 필요했고 나의 경우에는 unique key를 활용하여 해당 key로 이벤트리스너를 등록할 때, 이벤트저장소라는 공간에 해당 이벤트를 저장하였다. 이후에 컴포넌트가 재생성되었을 때는 동일한 key값으로 이벤트저장소에 접근하여 기존의 이벤트가 존재했다면 이벤트를 해제해주는 방식으로 구현하였다.
class EventStore {
cache: Map<string, ICache[]>;
constructor() {
this.cache = new Map();
}
cachingEventListener(
key: string,
target: EventTargetType,
eventListener: IEventListener,
) {
// 이벤트리스너를 등록할 때, 이벤트저장소에도 저장하는 과정
}
removeAllEventListener(key: string) {
// 기존의 이벤트리스너를 해지해주는 과정
}
}
export default new EventStore();
다음과 같이 해당 모듈을 내보낼 때, new 키워드를 사용하여 반환하게끔 작성한다면, 프로젝트 내에서 단 하나의 instance만을 가질 수 있게 된다.
ES6 Modules are singletons - the instance is created when module is loaded.
버튼, input창과 같이 홈페이지내에서 스타일이 비슷비슷한 요소들은 @mixin 기능을 활용한다면 재사용성면에서 유용하기 때문에 유지보수가 쉬워진다는 장점이 있다.
@mixin btn {
border: none;
font-size: 1rem;
font-weight: 700;
&:hover {
cursor: pointer;
}
}
.btn--submit {
@include btn;
background-color: red;
}
.btn--reset {
@include btn;
background-color: green;
}
Arguments를 활용해서 커스텀화 할 수도 있다.
@mixin btn($padding, $background-color) {
border: none;
font-size: 1rem;
font-weight: 700;
background-color: $background-color;
&:hover {
cursor: pointer;
background-color: rgba($background-color, 0.5);
}
}
.btn--submit {
@include btn(10px 20px, red);
}