arrow function 답게 간편하게 앱을 만들어 보자.
setup. 초기 세팅한다.
util. 사용될 함수를 작성한다.
setEvent. 이벤트 등록한다.
mounted. 추가적인 기능을 수행한다.
상태 관리 및 리렌더링은 싸이클에서 관리하지 않는다.
추후에 Observer 패턴을 활용해서 직접 상태를 관리하자.
import { RecentlyViewedStore } from "../../stores";
import { homeState } from "./_state";
export const AddedList = () => {
// setup. 초기 세팅한다.
const root = document.createElement("div");
root.innerHTML = `
<h5>등록된 아이템 목록</h5>
<div class="added__wrapper"></div>
`;
const itemList = root.querySelector(".added__wrapper");
// util. 사용될 함수를 작성한다.
const renderItemList = () => {
itemList.innerHTML = `
${homeState.list
.map((name) => `<span class="added__item">${name}</span>`)
.join("")}
`;
};
// setEvent. 이벤트 등록한다.
root.addEventListener("click", (e) => {
const isItem = e.target.classList.contains("added__item");
if (isItem) {
RecentlyViewedStore.dispatch("ADD_ITEM", { text: e.target.innerText });
}
});
// mounted. 추가적인 기능을 수행한다.
renderItemList();
homeState.subscribe(renderItemList);
return root;
};
리렌더링될 요소를 파악해서 별도로 렌더링 관리한다.
vanilla의 장점은 내가 원하는대로 렌더링을 관리할 수 있다는 점이다.
상태 변경에 따라 변경이 된 부분만 리렌더링이 진행되도록 하자. ( Observer 패턴 활용 )
이벤트를 등록할 때 최대한 버블링을 잘 활용하자.
className === ''
이 아닌 classList.contains
을 사용하는 것은 덤! ( 여러 클래스 이름을 사용할 수 있기에 )
코드 위치가 일관적이어야 한다.
같은 스코프에서 모든 라이프싸이클이 담겨지기에 파일마다 위치가 다르면 유지보수하기 굉장히 힘들다.
ex) subscribe
관련 작업 항상 최하단에서 한다.
DOM API를 최대한 잘 활용해야 한다.
DOM의 기능이 정말 많이 있다.
DOM 관련 closest
insertAdjacentHTML
...
이벤트 관련 onsubmit
keydown
ontransitionend
...
최대한 컴포넌트를 잘게 쪼개자.
import { HomeForm } from "./HomeForm";
import { AddedList } from "./AddedList";
import { RecentlyViewedList } from "./RecentlyViewedList";
export const HomePage = () => {
const app = document.querySelector("#app");
app.appendChild(HomeForm());
app.appendChild(AddedList());
app.appendChild(RecentlyViewedList());
};
만든 컴포넌트는 appendChild
을 통해서 추가한다. innerHTML로 추가하게 되면 등록한 event가 실종된다..