쇼핑몰 예제를 진행하면서 헤더나 검색창 부분이 중복 사용되면서 이전에 연구해봤던 웹컴포넌트를 사용해보기로 했다.
이전에 포스팅했던 방식으로 진행을 해보았는데 막상 실전에서 사용해보니 shadow.root로 컴포넌트에 벽을 쳐 두니 생각보다 번거로운 부분이 너무 많았다. 그래서 그냥 모두 오픈시켜서 사용해보았고 이렇게 해도 큰 탈 없이 잘 진행되었다.
class HeaderComponent extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `
<style>
#home-btn {
border: 2px, solid, black;
}
</style>
<div>
<button id="home-btn">home</button>
<button id="login-btn">로그인</button>
<button id="logout-btn" style="display: none;">로그아웃</button>
<button id="admin-btn">admin</button>
<div id="cart-btn-container"></div>
</div>
`;
// 버튼 이벤트 리스너 추가
this.querySelector('#home-btn').addEventListener('click', () => {
window.location.href = '/';
});
this.querySelector('#login-btn').addEventListener('click', () => {
window.location.href = '/login';
});
this.querySelector('#logout-btn').addEventListener('click', () => {
sessionStorage.removeItem('token');
window.location.href = '/login';
});
this.querySelector('#admin-btn').addEventListener('click', () => {
window.location.href = '/admin/product';
});
// 토큰 유무에 따라 로그인/로그아웃 버튼 표시 설정
this.toggleAuthButtons();
}
// 로그인/로그아웃 버튼 토글 메서드
toggleAuthButtons() {
const token = sessionStorage.getItem('token');
const loginBtn = this.querySelector('#login-btn');
const logoutBtn = this.querySelector('#logout-btn');
if (token) {
// 토큰이 있으면 로그아웃 버튼 표시, 로그인 버튼 숨기기
logoutBtn.style.display = 'block';
loginBtn.style.display = 'none';
} else {
// 토큰이 없으면 로그인 버튼 표시, 로그아웃 버튼 숨기기
logoutBtn.style.display = 'none';
loginBtn.style.display = 'block';
}
}
}
// 커스텀 엘리먼트 정의
customElements.define('header-component', HeaderComponent);
이러면 이 컴포넌트를 불러온 다른 html의 js에서도 얼마든지 컴포넌트 제어가 가능했다.
공통되는 엘리먼트나 제어는 컴포넌트에 넣고 커스터마이즈되는 엘리먼트나 제어는 밖에서 이루어지면 되는 것이었다!
특히 웹 컴포넌트는 커스터마이즈 속성 처리를 위해 slot이라는걸 제공하고 나도 이걸 이용해서 구현하는 것을 시도했었는데
이 slot의 문제가 html 상의 순서를 무시하고 나타나서 제어가 무지 힘들었다.
그래서 생각을 바꾼게 굳이 slot을 안쓰고 그냥 빈 div를 만들어두고 컴포넌트 밖에서 그 html 내용을 넣고 제어도 하면 되지 않을까 하고 시도해보았는데 잘 되었다.
<div>
<button id="home-btn">home</button>
<button id="login-btn">로그인</button>
<button id="logout-btn" style="display: none;">로그아웃</button>
<button id="admin-btn">admin</button>
<div id="cart-btn-container"></div>
</div>
여기를 보면 카트 버튼은 그냥 div로 id만 부여한 채 비어있는데
이 카트 버튼은 admin에서는 안보일거여서 일반 페이지에서만 넣어주려고 한다.
그럴 때 이런식으로 해당 html에서 내용을 넣어주고 제어를 했을 때 전혀 문제가 없었다.
즉, 굳이 slot을 사용안해도 되겠다고 판단되었다.
//장바구니 버튼
document.getElementById('cart-btn-container').innerHTML = `
<button id="cart-btn">장바구니</button>
`
const cartBTN = document.getElementById('cart-btn');
cartBTN.addEventListener('click', () => {
getCartPage();
});
아무튼 이렇게 사용방식에 변화를 주니 웹컴포넌트 사용이 좀 더 편해졌다.
리액트 안쓰고 컴포넌트를 해보려니 여러모로 힘들지만...그만큼 배우는 점도 많은 듯 하다.