본문 바로가기

Javascript

Javascript & TypeScript Essential - 패스트캠퍼스 챌린지 9일차

#패스트캠퍼스_환급_챌린지 https://bit.ly/3FVdhDa #9일차

 

페이징 구현하기

현재 작성된 프로그램은 강제로 최신 10개 글만 표시하도록 제한되어 있다.

이번시간에는 페이지를 이동하면서 다른 글들도 확인할 수 있도록 페이징 기능을 구현해보자.

1. 페이징 UI 만들기

function newsFeed () {
  
  const newsFeed = getData(NEWS_URL);
  
  const newsList = [];
  newsList.push('<ul>');
  for (let i = ((store.currentPage - 1) * 10); i < store.currentPage * 10; i++) {
    newsList.push(`
      <li>
        <a href="#${ newsFeed[i].id }">
        ${ newsFeed[i].title } (${ newsFeed[i].comments_count })
        </a>
      </li>
    `);
  }
  newsList.push('</ul>');
  newsList.push(`
    <div>
      <a href="#">이전 페이지</a>
      <a href="#">다음 페이지</a>
    </div>
  `)

  container.innerHTML = newsList.join('');
}

2. 현재 페이지를 변수에 담아 저장한다. 페이지 이동이나 내용보기에서 목록으로 이동 시 필요하다.

페이지와 같은 상태값을을 담을 수 있는 store 객체를 만들어서 store 상태값으로 저장한다.

store객체는 여러 상태값을 담는 객체로 앞으로 사용할 것이다.

그리고 이전 페이지와 다음 페이지 값으로 현재 페이지에 1을 더하거나 빼서 값을 넘긴다.

const store = {
	currentPage: 1
};

function newsFeed () {
  
  const newsFeed = getData(NEWS_URL);
  
  const newsList = [];
  newsList.push('<ul>');
  for (let i = 0; i < 10; i++) {
    newsList.push(`
      <li>
        <a href="#${ newsFeed[i].id }">
        ${ newsFeed[i].title } (${ newsFeed[i].comments_count })
        </a>
      </li>
    `);
  }
  newsList.push('</ul>');
  newsList.push(`
    <div>
      <a href="#${ store.currentPage - 1 }">이전 페이지</a>
      <a href="#${ store.currentPage + 1 }">다음 페이지</a>
    </div>
  `);

  container.innerHTML = newsList.join('');
}

이전 페이지 다음 페이지의 해시값과 내용보기 해시값 형태(#숫자)가 동일하기 때문에 router에서 처리하기 위해 페이지 이동 링크(#/page/페이지번호)와 내용보기 링크(#/show/글아이디)를 수정하자.

그리고 페이지 번호에 맞춰 글 목록이 표시 되도록 for 조건을 수정한다.

function newsFeed () {
  
  const newsFeed = getData(NEWS_URL);
  
  const newsList = [];
  newsList.push('<ul>');
  for (let i = ((store.currentPage - 1) * 10); i < store.currentPage * 10; i++) {
    newsList.push(`
      <li>
        <a href="#/show/${ newsFeed[i].id }">
        ${ newsFeed[i].title } (${ newsFeed[i].comments_count })
        </a>
      </li>
    `);
  }
  newsList.push('</ul>');
  newsList.push(`
    <div>
      <a href="#/page/${ store.currentPage - 1 }">이전 페이지</a>
      <a href="#/page/${ store.currentPage + 1 }">다음 페이지</a>
    </div>
  `);

  container.innerHTML = newsList.join('');
}

라우터 함수에서도 이동할 페이지 목록 함수를 호출할 것인지 내용보기 함수를 호출할 것인지 해시값을 이용해서 구분한다.

function router() {
  const routerPath  = location.hash;
  if (routerPath === '') {
    newsFeed();
  }
  else if (routerPath.indexOf('#/page/') >= 0) {
    store.currentPage = Number(routerPath.substr(7));	// 페이지번호를 숫자로 변환한다. !중요
    newsFeed();
  } else {
    newsDetail();
  }
}

내용 보기에서도 hash 값에서 아이디 값 추출하는 부분과 목록으로 이동 시 이전 페이지 번호를 포함하도록 수정해 보자.

function newsDetail () {
  const id = location.hash.substr(7);

  const newsContent = getData(CONTENT_URL.replace('@id', id));

  container.innerHTML = `
    <h1>${ newsContent.title }</h1>
    <div>
      <a href="#/page/${ store.currentPage }">목록으로</a>
    </div>
  `;

}

마지막으로 1페이지에서 이전 페이지로 이동 시 페이지 번호가 0으로 되는 문제점과 마지막 페이지에서 다음 페이지로 이동을 제한 할 수 있도록 수정하자.(삼항연산자 사용)

function newsFeed () {
  
  const newsFeed = getData(NEWS_URL);
  
  const newsList = [];
  newsList.push('<ul>');
  for (let i = ((store.currentPage - 1) * 10); i < store.currentPage * 10; i++) {
    newsList.push(`
      <li>
        <a href="#/show/${ newsFeed[i].id }">
        ${ newsFeed[i].title } (${ newsFeed[i].comments_count })
        </a>
      </li>
    `);
  }
  newsList.push('</ul>');
  newsList.push(`
    <div>
      <a href="#">이전 페이지</a>
      <a href="#">다음 페이지</a>
    </div>
  `)
  newsList.push(`
    <div>
      <a href="#/page/${ store.currentPage > 1 ? store.currentPage - 1 : 1 }">이전 페이지</a>
      <a href="#/page/${ store.currentPage < newsFeed.length / 10 ? store.currentPage + 1 : newsFeed.length / 10 }">다음 페이지</a>
    </div>
  `);

  container.innerHTML = newsList.join('');
}

이번시간까지 작성한 전체 소스이다.

const container = document.getElementById('root');
const ajax = new XMLHttpRequest();
const content = document.createElement('div');
const NEWS_URL ='https://api.hnpwa.com/v0/news/1.json';
const CONTENT_URL = 'https://api.hnpwa.com/v0/item/@id.json';

//공유되는 값
const store = {
  currentPage: 1
}

function getData (url) {
  ajax.open('GET', url, false);
  ajax.send();

  return JSON.parse(ajax.response);
}

function newsFeed () {
  
  const newsFeed = getData(NEWS_URL);
  
  const newsList = [];
  newsList.push('<ul>');
  for (let i = ((store.currentPage - 1) * 10); i < store.currentPage * 10; i++) {
    newsList.push(`
      <li>
        <a href="#/show/${ newsFeed[i].id }">
        ${ newsFeed[i].title } (${ newsFeed[i].comments_count })
        </a>
      </li>
    `);
  }
  newsList.push('</ul>');
  newsList.push(`
    <div>
      <a href="#">이전 페이지</a>
      <a href="#">다음 페이지</a>
    </div>
  `)
  newsList.push(`
    <div>
      <a href="#/page/${ store.currentPage > 1 ? store.currentPage - 1 : 1 }">이전 페이지</a>
      <a href="#/page/${ store.currentPage < newsFeed.length / 10 ? store.currentPage + 1 : newsFeed.length / 10 }">다음 페이지</a>
    </div>
  `);

  container.innerHTML = newsList.join('');
}


function newsDetail () {
  const id = location.hash.substr(7);

  const newsContent = getData(CONTENT_URL.replace('@id', id));

  container.innerHTML = `
    <h1>${ newsContent.title }</h1>
    <div>
      <a href="#/page/${ store.currentPage }">목록으로</a>
    </div>
  `;

}

function router() {
  const routerPath  = location.hash;
  if (routerPath === '') {
    newsFeed();
  }
  else if (routerPath.indexOf('#/page/') >= 0) {
    store.currentPage = Number(routerPath.substr(7));
    newsFeed();
  } else {
    newsDetail();
  }
}


window.addEventListener('hashchange', router);

router();

ch03_06.페이징 구현하기