폴더 구조 html 태그로 나타내기

jh·2023년 10월 18일
0

노션 사이드바

이 사진처럼(노션) 폴더의 구조를 시각화하는 걸 해보았다.
제일 먼저 각 파일들과 그 자식 파일들을 계층적으로 나타내는 것을 우선적으로 코드를 작성했다.

 [
    {
      id: 1, // Document id
      title: '파일1', // Document title
      documents: [
        {
          id: 2,
          title: '파일1의 자식 파일2',
          documents: [
            {
              id: 3,
              title: '파일2의 자식 파일3',
              documents: [],
            },
          ],
        },
        {
          id: 5,
          title: '파일 1의 자식 파일 5',
          documents: [],
        },
      ],
    },
    {
      id: 4,
      title: 파일 4,
      documents: [],
    },
  ]

데이터는 트리 형태와 유사하게 구성되어있고, 해당 파일의 자식 파일은 documents라는 배열에 들어가 있다.

<ul><li>를 중첩하는 방식

 <li>
    <input type="checkbox" id="root">
    <label for="root">ROOT</label>
    <ul>
      <li>
        <input type="checkbox" id="node1">
        <label for="node1" class="lastTree">node1</label>
      </li>
      <li>
        <input type="checkbox" id="node2">
        <label for="node2">node2</label>
        </ul>
        ....

이런 식으로 <li> 태그 안에 다른 <ul> , <li> 를 중첩시켜서 나타낼 수 있다

  • 이렇게 하면 장점은 css를 적용하지 않아도, 부모 파일과 자식 파일의 계층구조가 시각적으로 보인다.
  • 하지만 뭔가 html이 복잡하게 중첩되는 느낌...(실제로 노션의 html을 뜯어봐도 이런 방식을 사용하고 있지는 않음)
  • 그런데 시멘틱 태그의 관점에서 생각해본다면, 이 방법이 제일 의미에 부합하지 않나..라는 생각이 든다
const renderTreeByList = (data, parentElement) => {
    const $ul = document.createElement('ul')
    
    for (const item of data) {
      const $li = document.createElement('li')
      const $span = document.createElement('span')
      $span.innerText = item.title
      $li.appendChild($span)
      if (item.documents.length) {
        this.renderTreeByList(item.documents, $li)
      }
      
      $ul.appendChild($li)
    }
      parentElement.appendChild($ul)
  }
  • 재귀함수를 사용해서 해당 node는 파일명은 <li> 태그 안에 <span>으로 넣어주면 되고, 자식 파일들은 <ul>을 중첩시켜주면 된다
  • 말로 설명하기 굉장히 어렵지만, 재귀함수를 하나씩 뜯어보면 이해할 수 있음

div만 사용해서 중첩

const renderTreeByDiv = (data, parentElement) => {
    for (const item of data) {
      $node.textContent = item.title
      $node.classList.add('node')
      parentElement.appendChild($node)
      if (item.documents.length) {
        this.renderTree(item.documents, $node)
      }
    }
  }
  • div 태그 안에 div를 중첩시키는 방법으로, 다른 태그들 없이 div만 사용하기 때문에 코드가 간결해지기는 함

  • 하지만 의미가 없는 코드라는 생각이 듦

    • (실제 notion의 html을 뜯어봐도 div로 만들어 놓기는 함)
  • 대신 자동적으로 계층구조(들여쓰기)를 만들어주지 않기 때문에, css를 설정해줘야 함

    • 사실 저 들여쓰기 css가 제일 어려웠는데... 그냥 margin만 설정해주면 되는거였다
    .node {
    margin-left : 20px;
    }
  • margin은 부모 요소의 왼쪽 가장자리(왼쪽 여백)을 기준으로 함

  • 한마디로 나의 부모 태그가 부모의 부모(나에게는 조상 태그)보다 20px 왼쪽에서 떨어져 있다면,
    나는 부모를 기준으로 20px 왼쪽으로 떨어져 있게 되고, 조상을 기준으로는 40px 왼쪽으로 떨어져 있게 되면서 트리의 깊이에 따라 인덴트(들여쓰기) 효과를 줄 수 있게 된다

    결과

이제 여기에 버튼들을 추가해서 감추기, 삭제(이건 어려울거같음)를 추가해볼 생각

0개의 댓글