// 서버 (네트워크 너머에 있는 데이터) 가져오는 도구 = ajax
const ajax = new XMLHttpRequest(); // new XMLHttpRequest()가 반환하는 값을 저장하는 저장소 만들어주기.
// ajax라는 변수 통해서 XMLHttpRequest가 제공하는 도구를 사용할 수 있음.
const NEWS_URL = 'https://api.hnpwa.com/v0/news/1.json'; // 바뀔 가능성이 있는 데이터는 따로 변수로 빼주는 것이 좋음.
// 데이터 가져오기
ajax.open('GET', NEWS_URL, false); // false : 가져오는 데이터를 동기적으로 가져오겠다(처리하겠다)는 뜻
ajax.send(); // open만 한다고 해서 데이터 가져오는 것은 아니고, send라는 함수 호출하면 데이터 가져오게 됨.
// 데이터 처리
// ajax.response; : 데이터 어디 들어왔는지 확인 -> response라는 값에 들어있음.
// response에 있는 데이터를 js에서 다루기 쉽도록 Preview탭처럼(= 객체 ) 바꾸기. 즉 응답값을 객체로 바꾸기
// -> 어떤 응답 값이는 다 객체로 바꿀 수 있는 것은 아니고, 응답 값으로 온 형식이 객체로 바꿀 수 있는 형식인 json형식이기 때문에 가능한 것.
// console.log(ajax.response); // 콘솔로 찍어보고 확인!
// jSON데이터를 객체로 바꾸기
// 반환한 객체를 변수로 받아주기, JSON.parse() : 괄호 안에 입력으로 받은 JSON데이터를 객체로 바꿔서 반환해줌.
const newsFeed = JSON.parse(ajax.response);
// console.log(newFeed); // 콘솔로 찍어보고 확인!
const ul = document.createElement('ul'); // ul태그 생성, document라고 하는 도구가 바로 HTML을 조작하는 데 필요한 모든 도구들을 제공해 주는 도구.
for (let i = 0; i < newsFeed.length; i++) {
const li= document.createElement('li'); // li는 매번 새로 만들어 지기 때문에 for문안에 만들어주기.
li.innerHTML=newsFeed[i].title;
ul.appendChild(li);
}
document.getElementById('root').appendChild(ul); // ul 태그 만든 것을 root 하위에 넣어주기. appendChild : 자식추가
현재 newsFeed길이만큼 리스트를 받아오는 형태로 화면에 출력된다 ~!
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'; // id값 마킹하기 위해 @사용(방법 여러가지 있음.)
// 데이터 가져오기
ajax.open('GET', NEWS_URL, false);
ajax.send();
// 데이터 처리
const newsFeed = JSON.parse(ajax.response);
const ul = document.createElement('ul'); .
// 해시체인지
// 해시체인지가 발생했을 때 함수가 호출됨.
// 각각의 것들의 내용이 실제로 바뀌어야 해시체인지가 일어남.
// 해시 체인지 안에 있는 함수가 각각의 글들이 한번씩 클릭 될 때마다 호출되는 상황 만들기.
window.addEventListener('hashchange',function(){
// hashchange일어났을 때 id 알수 있는 방법-> location이라는 객체로!(주소와 관련된 다양한 정보 제공) 해시는 주소에 붙어있음. ==> location 객체에 해시라고 하는 속성으로 데이터를 넘겨줌.
const id =location.hash.substr(1); // substr : 내가 쓰고 싶은 위치 값만 지정해 주면 그 이후부터의 값까지 씀. 시작 값은 0부터 씀 , console.log(location.hash)로 찍어보면 #아이디값 이 출력되서 #을 제외해줘야 하기때문에 1이라고 입력!
// 첫번째 위치부터 나머지 뒤에 있는 문자열들만 반환.
// CONTENT_URL에 @id를 위에서 생성한 id로 바꿔주기. replace : 값을 대체해 주는 문자열 함수
ajax.open('GET', CONTENT_URL.replace('@id',id), false);
ajax.send();
const newsContent = JSON.parse(ajax.response);
const title = document.createElement('h1');
title.innerHTML=newsContent.title;
content.appendChild(title);
});
for (let i = 0; i < newsFeed.length; i++) {
const li = document.createElement('li');
const a = document.createElement('a');
a.href=`#${newsFeed[i].id}`;
a.innerHTML=`${newsFeed[i].title}(${newsFeed[i].commnets_count})`;
li.appendChild(a);
ul.appendChild(li);
}
container.appendChild(ul); // ul 태그 만든 것을 root하위에 넣어 주기. appendChild: 자식 추가
container.appendChild(content);
url창을 보면! 링크 클릭할 때마다 id값 다르게 노출됨을 알 수 있음!
🚨 🚨 🚨
단, 현재는 title링크를 클릭 하는 대로 계속 화면에 title이 이어서 출력된다..!
또한, DOM API를 이용해서 UI를 만든 탓에 UI가 어떻게 생겼는지 잘 파악이 안됨.
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';
function getData(url){
// 데이터 가져오기
ajax.open('GET', url, false);
ajax.send();
return JSON.parse(ajax.response);
}
const newsFeed = getData(NEWS_URL);
const ul = document.createElement('ul');
window.addEventListener('hashchange',function(){
const id =location.hash.substr(1);
const newsContent = getData(CONTENT_URL.replace('@id',id));
const title = document.createElement('h1');
title.innerHTML=newsContent.title;
content.appendChild(title);
});
for (let i = 0; i < newsFeed.length; i++) {
const div = document.createElement('div');
const li= document.createElement('li');
const a = document.createElement('a');
div.innerHTML=`
<li>
<a href="#${newsFeed[i].id}">
${newsFeed[i].title} (${newsFeed[i].comments_count})
</a>
</li>`
ul.appendChild(div.firstElementChild); // = ul.appendChild(div.children[0]); : 첫번째 자식요소 가져오기.
}
container.appendChild(ul);
container.appendChild(content);
1. getData 함수를 생성해서 코드 중복을 막아주고
2. 문자열을 가지고 HTML을 만들어서 마크업 구조를 한눈에 보기 쉽게 코드를 작성했음!!✨ innerHTML : DOM API가 제공하는 속성. 문자열을 넣었는데 문자열안에 HTML태그 포함되어 있으면 그 자체를 DOM API로, 즉 HTML로 실제로 변환하는 것이 자동으로 처리된다는 뜻.!
=> HTML문자열로 만들면 마크업 구조가 굉장히 잘 보인다는 것을 명확하게 알 수 있음.
🚨 🚨 🚨
현재 까지 만든 화면의 문제점 : 목록 화면과 title이 같은 화면에 계속 보이고 있음!
+ title을 클릭할 때마다 같은 화면에 추가되는 버그까지..
=> 여러 개의 화면을 갖고 있는 형태의 UI를 구성한다면, 화면에 보여지는 건 사용자가 보고있는 현재의 화면이고! 이전의 화면은 사라져야함!!
문제를 개선해보자 ~~~ 😎 ! !
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';
function getData(url){
// 데이터 가져오기
ajax.open('GET', url, false);
ajax.send();
return JSON.parse(ajax.response);
}
const newFeed = getData(NEWS_URL);
const ul = document.createElement('ul');
window.addEventListener('hashchange',function(){
const id =location.hash.substr(1);
const newsContent = getData(CONTENT_URL.replace('@id',id));
const title = document.createElement('h1');
container.innerHTML=`
<h1>${newsContent.title}</h1>
<div>
<a href="#">목록으로</a>
</div>
`;
});
// 배열 사용해서 만들고자 하는 문자열들을 배열 안에 요소로 차곡차곡 쌓아 놓고 마지막에 합쳐서 하나의 문자열로 만드는 방식 (흔히 사용되는 방법)
const newsList=[];
newsList.push('<ul>'); // 위치를 기억하는건 매우 어렵기에 배열 요소에 가장 마지막에 새로 추가하는 push 메소드 사용.
// for문 안에는 li태그 문자열 넣기
// 이 반복문은 li태그 문자열을 만들어서 newsList배열에 추가하는 역할. (자연스럽게 DOM API소멸)
for (let i = 0; i < newsFeed.length; i++) {
newsList.push(`
<li>
<a href="#${newsFeed[i].id}">
${newsFeed[i].title} (${newsFeed[i].comments_count})
</a>
</li>
`); // createElement로 만들었던 div 필요없어짐.
}
newsList.push('/<ul>'); // ul태그 닫기
// 오버라이트하기 위해 innerHTML사용.
// newsList는 배열이라 innerHTML에 넣을 수 없음..innerHTML에는 하나의 문자열이 들어가야 함.
// newsList는 배열을 여러개 갖고 있고, 내용 자체는 태그들. -> 이것들을 하나의 문자열로 합치기.
container.innerHTML = newsList.join(''); // join() : 하나의 문자열로 합치는 함수. 구분자 제거위해 빈 문자열 넣어주기.
1. 내용 화면으로 진입 = hashchange의 이벤트 핸들러.
=> hashchange의 이벤트 핸들러를 바꿈!
2. title 클릭하면 화면이 전환되면서 글 내용 화면으로 진입되는 것 확인 가능.
3. '목록으로' 클릭 했을 때 아직 글 목록으로 가지 못함..!!
const container = document.getElementById('root');
// 서버 (네트워크 너머에 있는 데이터) 가져오는 도구 = ajax
const ajax = new XMLHttpRequest(); // new XMLHttpRequest()가 반환하는 값을 저장하는 저장소 만들어주기.
// ajax라는 변수 통해서 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'; // id값 마킹하기 위해 @사용(방법 여러가지 있음.)
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 = 0; i < newsFeed.length; i++) {
newsList.push(`
<li>
<a href="#${newsFeed[i].id}">
${newsFeed[i].title} (${newsFeed[i].comments_count})
</a>
</li>
`);
}
newsList.push('</ul>');
container.innerHTML = newsList.join('');
}
function newsDetail(){
const id =location.hash.substr(1);
const newsContent = getData(CONTENT_URL.replace('@id',id));
const title = document.createElement('h1');
container.innerHTML=`
<h1>${newsContent.title}</h1>
<div>
<a href="#">목록으로</a>
</div>
`;
}
// 라우터 생성 - 화면 전환 구현 (해시 값 갖고 오기)
// 페이지 시작하자 마자 게시글 보여주기 => newsFeed 함수 호출
// router함수는 newsDetail함수와 달리 화면을 전환하는 목적이 있기 때문에, 특정 화면의 어떠한 데이터에 대해서는 관심x
function router(){
// 해시값 전체 가져오기
const routePath = location.hash;
if(routePath ===''){
newsFeed();
}else{
newsDetail();
}
}
// 해시체인지에 router연결
window.addEventListener('hashchange', router);
// 해시체인지가 일어날 때 동작하는 함수를 기존의 newsDetail이 아니라 router에게 주면 라우터가 해시 바뀔때 마다 동작하게 됨.
// 라우터 안에서 어떤 해시냐에 따라 글 목록 보여줄 때도 있고, 내용 보여줄 때도 있고.. 이렇게 동작하게 됨.
// 라우터 호출
router();
// 라우터 -> 화면 전환되어야 할 때 라우터가 판단해서 해당 화면으로 전환시킴.
// 현재 화면이 전환되어야 할 때는 해시체인지가 일어날 때 (해시가 바뀌는 걸 화면 전환을 위한 트리거로써 사용중.)
1. 글 목록 화면을 함수로 묶어줌! => newsDetail
✨ Router : 일종의 중계기 같은 것. 화면을 중계. 화면 전환 화면이 여러개 있다면 어떤 상태에서는 A화면, 어떤 상태에서는 B화면, 어떤 상태에서는 C화면.....을 보여줄 수 있는 것!
2. 페이지 시작 시, 글 목록이 잘 보이고 글 목록 (title)을 클릭해서 내용을 보면 내용도 잘 표시 됨!
'목록으로' 를 클릭하면 글 목록으로 화면이 잘 전환됨.
3. 라우터 구현으로 화면 전환 자연스럽게 잘 일어남 ~~!
if(routePath ===''){
newsFeed();
}
-> 글 목록의 링크는 #
이다.
그러면 location.hash
에 #
이 들어왔을 텐데 왜 이게 true일까? 라고한다면!
실제로 location.hash
에 #
만 들어 있을 경우에는 빈값을 반환함! 그래서 이 코드가 작동하 는 것~~!
그래서 라우터만 구현했을 뿐이지만, 글 목록도 잘 작동하는 것을 확인할 수 있음 😋