Idea :
- AddCard의 마운트 될 때(mounted 훅) window에 이벤트를 바인딩!
- 그리고 destroyed훅에서 이벤트를 해제한다.
addEventListener & removeEventListener
window.addEventListener('click', clickHandler, false);
window.removeEventListener('click', clickHandler, false);
- 익명함수를 사용하지 않으면, 이벤트핸들러를 바인딩하고 삭제할때 용이하다.
Node.contains(otherNode)
: 인자로 주어지는 노드가 해당 노드에 포함되어 있는지 여부를 true/false값으로 리턴
코드
//AddCard.vue
//methods
bindEvent() {
const self = this;
document.querySelector("body")
.addEventListener("click", this.onClickOutSide, false);
},
//1.
onClickOutSide(event) {
const $target = event.target;
const $parent = this.$el.closest(".list-item");
if ( $parent.contains($target) ||
$target.classList.contains("addCard__toggle")
) {
return;
}
this.$emit("close");
},
//mounted
//2.
document.querySelector("body").addEventListener("click", this.onClickOutSide, false);
//destroyed
//3.
document.querySelector("body").removeEventListener("click", this.onClickOutSide, false);
- 클릭 시 실행되는 함수, Node.conatins를 활용해, 클릭된 엘리먼트가 "list-item" 엘리먼트에 포함되어 있지 않으면, AddCard 컴포넌트를 닫는다. 이때, "addCard__toggle" 엘리먼트가 클릭되었을 경우도 제외했는데 이유는 2번에서 이어서 설명하겠습니다.
- this.$el을 참조하기위해서 컴포넌트가 마운드 된 이후(DOM에 렌더링 된 이후), 클릭 이벤트를 바인딩했습니다. 그런데, 마운트된 순간과 거의 동시에 이벤트가 바인딩되고 실행되어서,
$parent.contains($target) === false
가 되었고, 바로 컴포넌트가 닫혔습니다.$target === "addCard__toggle"
엘리먼트 였고, 따라서 강제로 이 엘리먼트를 제외시켰습니다. ===> 좋은 방법 찾기!- 컴포넌트가 돔에서 제거되면, body에 걸려있는 클릭 이벤트를 제거합니다.
- Card 컴포넌트는 "중첩 라우팅"을 이용해서 Board.vue의
<router-view></router-view>
를 통해서 렌더링되고 있다.- Modal 컴포넌트를 통해서 만들었지만, 기존 Modal을 사용한 컴포넌트와 다르게,
$emit("close")
를 이용하지 않고,<router-link></router-link>
를 이용해서 닫기처리를 했다.
<header slot="header" class="cardView__header">
<span class="cardView__title">{{ card.title }}</span>
<router-link :to="`/b/${board.id}`" class="cardView__close">
×
</router-link>
</header>
<footer slot="footer" class="cardView__footer">
<b-button
variant="dark"
class="cardView__button"
@click="goBoard"
>Ok</b-button
>
</footer>
goBoard() {
const bid = this.board.id;
this.$router.push(`/b/${bid}`);
},
<router-link></router-link>
를 통해서 Card 컴포넌트를 닫는다. => 라우팅 경로가 변경되므로, Board.vue 내부의<router-view></router-view>
에 Card컴포넌트가 렌더링되지 않는다.
goBoard()
라는 메소드를 이용해서<router-link></router-link>
를 이용하지않고, 라우팅을 변경하는 로직을 작성했다.