기능 구현
- Sidabar 메뉴 토글
- Sidebar Drawer 토글
- Ordal Modal 토글
- Bookmark 버튼 토글
const sidebarMenuButton = document.querySelector('.gnb-icon-button')
const sidebar = document.querySelector('.sidebar')
const sidebarOverlay = document.querySelector('.overlay')
function openSidebar() {
sidebar.classList.add('is-active')
sidebarOverlay.classList.add('is-active')
}
sidebarMenuButton.addEventListener('click', openSidebar)
function closeSidebar() {
sidebar.classList.remove('is-active')
sidebarOverlay.classList.remove('is-active')
}
sidebarOverlay.addEventListener('click', closeSidebar)
sidebar 메뉴 클릭 시, is-active class를 추가해주어 sidebar와 overlay를 활성화 시켜주었고, 함수를 선언하여 가독성을 높여주였다.
const sidebarNav = document.querySelector('.sidebar-nav')
sidebarNav.addEventListener('click', (e) => {
if (e.target.classList.contains('drawer-menu-button')) {
const drawerMenu = e.target.closest('div')
drawerMenu.classList.toggle('is-open')
drawerMenu.classList.toggle('is-active')
}
})
첫 번째 방법으로는 이벤트 위임 방식을 사용하였다. drawer-menu-button
의 부모인 sidebar-nav
에 click 이벤트를 활성화시켜준뒤, e.target.closest
메서드를 활용하여 is-open, is-active class를 추가해주어 drawer toggle 기능을 추가했다.
const drawerMenuButtonList = document.querySelectorAll(
'.sidebar-nav .drawer-menu-button'
)
function toggleDrawerMenu() {
const drawerMenu = this.parentNode
drawerMenu.classList.toggle('is-open')
drawerMenu.classList.toggle('is-active')
}
drawerMenuButtonList.forEach((button) => {
button.addEventListener('click', toggleDrawerMenu)
})
두 번째 방법으로는, querySelectorAll
을 이용하여 drawer-menu-button
을 모두 찾은 뒤, drawer-menu-button에 각각 click 이벤트를 활성화시켜주는 방법이다.
추가적으로, toggleDrawerMenu는 일반 함수
로서 addEventListener의 콜백 함수로 넘겨졌기 때문에, this가 event.currentTarget 프로퍼티와 동일한 값
을 가진다. 따라서 toggleDrawerMenu함수에서 this.parentNode
로서 작성이 가능하다.
반대로, toggleDrawerMenu를 화살표 함수
로 작성을 하였다면 렉시컬 this는 동작이 완전히 달라지기 때문에 this를 통해 요소에 접근할 수 없고, event.target.parentNode
로 접근이 가능하다.
const orderCta = document.querySelector('.order-cta')
const [orderCtaBookmarkButton, orderCtaBuyButton] = orderCta.children
const orderModal = document.querySelector('.order-form-modal')
const orderModalOverlay = document.querySelector('.overlay')
function openOrderModal() {
orderModal.classList.add('is-open')
orderModalOverlay.classList.add('is-active')
}
orderCtaBuyButton.addEventListener('click', openOrderModal)
function closeOrderModal() {
orderModal.classList.remove('is-open')
orderModalOverlay.classList.remove('is-active')
}
orderModalOverlay.addEventListener('click', closeOrderModal)
const [orderCtaBookmarkButton, orderCtaBuyButton] = orderCta.children 에서 orderCtaBookmarkButton, orderCtaBuyButton
을 es6+ 문법인 비구조화 할당 (destructuring assignment)
을 이용하여 선언해주었다.
orderCta.children 은 자식 2개를 가지고 있어, 배열 형태로 생성된다. 비구조화 할당 문법으로 배열 안의 원소를 각각 새로운 이름으로 선언해주었다.
북마크 버튼 클릭을 했을 때, 두 가지의 기능을 추가하였다.
1. 북마크 클릭 시, is-active 활성화 (아이콘 변경)
2. 북마크 클릭 시, count +1
const orderCta = document.querySelector('.order-cta')
const [orderCtaBookmarkButton, orderCtaBuyButton] = orderCta.children
function toggleOrderCtaBookmark() {
const [icon, countSpan] = this.children // 비구조화 할당
const count = Number(countSpan.textContent.replaceAll(',', ''))
let newCount = count
if (this.classList.contains('is-active')) {
icon.classList.replace('ic-bookmark-filled', 'ic-bookmark')
newCount--
} else {
icon.classList.replace('ic-bookmark', 'ic-bookmark-filled')
newCount++
}
countSpan.textContent = newCount.toLocaleString()
countSpan.setAttribute('aria-label', `북마크 ${newCount.toLocaleString()}회`)
this.classList.toggle('is-active')
}
orderCtaBookmarkButton.addEventListener('click', toggleOrderCtaBookmark)
18,302
숫자를 +1 하기 위해서 처음에는 콤마를 제거하는 함수를 만들고, 숫자를 +1 하고 마지막으로 다시 콤마를 추가해주는 함수를 또 만들어서 복잡하게 구현을 하였다.
이 과정을 skip 할 수 있게 해줄 수 있는 toLocaleString
메서드를 이용하면 간결하게 구현할 수 있다.