Tree UI
- Tree UI는 화면을 구성할 때 재귀를 사용하는 가장 대표적인 예시이다.
만들고자 하는 간단한 HTML DOM 구조
(예: 음료 -> 콜드브루 -> 나이트로 콜드브루)
<ul id="root">
<li>
<input type="checkbox" checked />
<span>음료</span>
<ul>
<li>
<input type="checkbox" />
<span>콜드브루</span>
<ul>
<li>나이트로 콜드 브루</li>
<li>돌체 콜드 브루</li>
<li>제주 비자림 콜드 브루</li>
<li>콜드 브루</li>
</ul>
</li>
</ul>
</li>
</ul>
메뉴 데이터 (길어서 생략)
더보기
const menu = [
{
type: 'group',
name: '음료',
children: [
{
type: 'group',
name: '콜드 브루',
children: [
{ type: 'item', name: '나이트로 콜드 브루' },
{ type: 'item', name: '돌체 콜드 브루' },
{ type: 'item', name: '제주 비자림 콜드 브루' },
{ type: 'item', name: '콜드 브루' },
],
},
{
type: 'group',
name: '프라푸치노',
children: [
{ type: 'item', name: '애플 쿠키 크림 프라푸치노' },
{ type: 'item', name: '더블 에스프레소 칩 프라푸치노' },
{ type: 'item', name: '모카 프라푸치노' },
{ type: 'item', name: '피스타치오 크림 프라푸치노' },
],
},
{
type: 'group',
name: '블렌디드',
children: [
{ type: 'item', name: '망고 바나나 블렌디드' },
{ type: 'item', name: '딸기 요거트 블렌디드' },
{ type: 'item', name: '자몽 셔벗 블렌디드' },
{ type: 'item', name: '피치 & 레몬 블렌디드' },
],
},
{
type: 'group',
name: '티',
children: [
{ type: 'item', name: '라임 패션 티' },
{ type: 'item', name: '민트 블렌드 티' },
{ type: 'item', name: '아이스 유스베리 티' },
{ type: 'item', name: '아이스 캐모마일 블렌드 티' },
],
},
{
type: 'group',
name: '주스',
children: [
{ type: 'item', name: '한방에 쭉 감당' },
{ type: 'item', name: '파이팅 청귤' },
{ type: 'item', name: '딸기주스' },
{ type: 'item', name: '도와주 흑흑' },
],
},
],
},
{
type: 'group',
name: '음식',
children: [
{
type: 'group',
name: '빵',
children: [
{ type: 'item', name: '트러플 미니 스콘' },
{ type: 'item', name: '보늬밤 몽블랑 데니쉬' },
{ type: 'item', name: '고소한 치즈 베이글' },
{ type: 'item', name: '미니 클래식 스콘' },
],
},
{
type: 'group',
name: '케이크',
children: [
{ type: 'item', name: '밀당 에그 타르트' },
{ type: 'item', name: '마스카포네 티라미수 케이크' },
{ type: 'item', name: '블루베리 쿠키 치즈 케이크' },
{ type: 'item', name: '부드러운 생크림 카스텔라' },
],
},
{
type: 'group',
name: '샌드위치',
children: [
{ type: 'item', name: '애플 까망베르 샌드위치' },
{ type: 'item', name: '트리플 머쉬룸 치즈 샌드위치' },
{ type: 'item', name: '로스트 치킨 샐러드 밀 박스' },
{ type: 'item', name: 'B.E.L.T 샌드위치' },
],
},
{
type: 'group',
name: '과일',
children: [
{ type: 'item', name: '하루 한 컵 RED' },
{ type: 'item', name: '한라봉 가득 핸디 젤리' },
],
},
{
type: 'group',
name: '스낵',
children: [
{ type: 'item', name: '리저브 초콜릿 세트' },
{ type: 'item', name: '로스티드 아몬드 앤 초콜릿' },
{ type: 'item', name: '마카롱' },
{ type: 'item', name: '자일리톨 캔디 크리스탈 민트' },
],
},
{
type: 'group',
name: '아이스크림',
children: [
{ type: 'item', name: '자바 칩 유기농 바닐라 아이스크림' },
{ type: 'item', name: '넛츠 초콜릿 아포가토' },
{ type: 'item', name: '바닐라 아포가토' },
],
},
],
},
{
type: 'group',
name: '굿즈',
children: [
{
type: 'group',
name: '머그',
children: [
{ type: 'item', name: '우리 한글 블랙 머그 473ml' },
{ type: 'item', name: '서울 투어 머그 355ml' },
{ type: 'item', name: '스타벅스 1호점 머그 400ml' },
{ type: 'item', name: '서울 제주 데이머그 세트' },
],
},
{
type: 'group',
name: '텀블러',
children: [
{ type: 'item', name: 'SS 부산 투어 텀블러 355ml' },
{ type: 'item', name: 'SS 블랙 헤리티지 오드리 텀블러 355ml' },
{ type: 'item', name: 'SS 에치드 실버 텀블러 473ml' },
],
},
{
type: 'group',
name: '악세사리',
children: [
{ type: 'item', name: '리저브 오렌지 카드 홀더' },
{ type: 'item', name: '스타벅스 1호점 에코백' },
{ type: 'item', name: '스타벅스 1호점 랩탑 파우치' },
],
},
],
},
{
type: 'group',
name: '카드',
children: [
{ type: 'item', name: '10000원권' },
{ type: 'item', name: '30000원권' },
{ type: 'item', name: '50000원권' },
{ type: 'item', name: '100000원권' },
],
},
];
만들고자 하는 간단한 DOM 구조
(예: 음료 -> 콜드브루 -> 나이트로 콜드브루)
코드
createTreeView
// 🟡 base case 예시 : menu = [{ name: '콜드 브루',
// children : [{type: 'item', name: '나이트로 콜드 브루'},
// {type: 'item', name: '제주 비자림 콜드 브루'}]}]
const root = document.getElementById('root'); // <ul id="root">
function createTreeView(menu, currentNode) {
menu.forEach(item => { // item(콜드 브루) -> {name: '콜드 브루', children: [{..},{..}]}
const listItem = document.createElement('li'); // li를 만든다.
if (item.children) { // item.children 있으면 (있음)
const input = document.createElement('input'); // input checkbox 만들고
input.type = 'checkbox';
const span = document.createElement('span'); // span 태그 만들어서
span.textContent = item.name; // '콜드 브루' 넣어줌
const subList = document.createElement('ul'); // children을 위한 ul 만들어서
listItem.append(input, span, subList); // li에 input, span, ul 넣음
createTreeView(item.children, subList); // 그뒤에 📌 재귀호출(2)
} else { // (2) item.children 없으면 (나이트로 콜드브루...)
listItem.textContent = item.name; // (2) li에 item.name 텍스트 삽입 ('콜드 브루')
}
currentNode.appendChild(listItem); // root에 listItem 넣기 // (2) subList에 li 넣기
});
}
createTreeView(menu, root);
map을 사용
const root = document.getElementById('root');
function createTreeView(menu, currentNode) {
menu.map(item => {
const listitem = document.createElement("li")
currentNode.append(listElements) // 미리 넣어준다.
if (item.type === 'item') {
listitem.textContent = item.name;
} else {
const input = document.createElement('input')
input.setAttribute('type', 'checkbox'); // setAttribute 써줌.
const span = document.createElement('span');
span.textContent = item.name;
const subList = document.createElement('ul')
listitem.append(input, span, ul);
createTreeView(item.children, subList)
}
})
}
createTreeView(menu, root);
참고 : 레퍼런스 코드 (reduce 사용)
// declarative solution
function createTreeView(menu, currentNode) {
const appendCollectionsInfo = function (currentNode, collections) {
const li = document.createElement('li');
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
const isItem = collections.type === 'item' ? true : false;
if (isItem) {
li.append(collections.name);
} else {
const groupName = document.createElement('span');
groupName.textContent = collections.name;
li.append(checkbox, groupName);
}
const haveChildren = Boolean(collections.children);
const children = collections.children;
if (haveChildren) {
const ul = document.createElement('ul');
createTreeView(children, ul);
li.append(ul);
}
currentNode.append(li);
return currentNode;
};
menu.reduce(appendCollectionsInfo, currentNode);
}
구현 결과
728x90
'FE > JavaScript' 카테고리의 다른 글
[JS] 꼬리재귀 (0) | 2023.04.27 |
---|---|
[JS] 하노이의 탑 (0) | 2023.04.20 |
[JS] JSON.stringify 재귀를 이용하여 직접 구현하기 (0) | 2023.04.12 |
[JS] JSON 개요 (JavaScript Object Notation) (0) | 2023.04.12 |
[JS] 재귀 (0) | 2023.04.11 |