리액트 프로젝트 템플릿 작성하기
1. npm install -g yarn
2. yarn -version
3. yarn create react-app template2023
4. yarn init --force 엔터 한 후 질문지에 대해 모두 엔터 치면 자동 완성됨
현재 페이지가 몇 번째 페이지인지 알고 있어야 한다 → 변하는 값이니 let으로 설정
현재 페이지가 몇번째 페이지인지 기억하는 변수가 필요하다
const store = { currentPage: 1 }
이전페이지일 경우, 내가 현재 바라보는 페이지를 기준으로 -1 한다
주의할 점은 -1은 되지 않아야 한다(페이지는 1부터 시작하기에) → 삼항연산자 이용
// store.currentPage가 1보다 크면 -1하고 아니라면 1 유지 store.currentPage > 1 ? store.currentPage - 1 : 1
다음 페이지일 경우, 내가 현재 바라보는 페이지를 기준으로 +1 한다
// 아래 코드는 3페이지까지 있는 경우를 가정 store.currentPage < 3 ? store.currentPage + 1 : 3
currentPage의 초기값은 1(전역변수로 선언함)
왜냐하면 상세 보기 화면으로 갔다가 다시 목록으로 돌아갈 때 이전에 바라보던 페이지로 돌아가려면 이 값이 공유되어야 함 → 그렇기에 전변으로 처리
내가 바라보는 페이지가 1번이면 배열의 0~9 인덱스만 호출
i = (1-1)*10 → 0 i < 1*10 → 10
내가 바라보는 페이지가 2번이면 배열의 10~19 인덱스만 호출
i = (2-1)*10 → 10 i < 2*10 → 20
내가 바라보는 페이지가 3번이면 배열의 20~29 인덱스만 호출
i = (3-1)*10 → 20 i < 3*10 → 30
for(let i = (store.currentPage - 1) * 10; i < store.currentPage * 10; i++) { }
<step 5>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>페이징 처리 - step5</title> <script defer src="./app.js"></script> </head> <body> <h2>실습제목: 페이징 처리</h2> <div id="title"></div> </body> </html>
const xhr = new XMLHttpRequest(); const NEWS = "https://api.hnpwa.com/v0/news/1.json"; const CONTENT = "https://api.hnpwa.com/v0/item/@id.json"; const container = document.querySelector("#title"); const divContent = document.createElement("div"); // 제목에 대한 상세내용 // 페이징 처리 <step 1> const store = { currentPage: 1, // 현재 내가 바라보는 페이지 번호 }; // 아래 함수의 사용처는 두 군데 // 요청 URL만 바뀜 나머지는 같음 -> 그래서 파라미터를 url로 줌 function getData(url) { xhr.open("GET", url, false); xhr.send(); return JSON.parse(xhr.responseText); } // 뉴스 목록 가져오기 function newsList() { const news = getData(NEWS); // li태그를 담을 배열 선언하기 const getList = []; // li 태그를 담기 전에 ul태그 먼저 담기 getList.push("<ul>"); // push()는 배열의 끝에 요소를 추가하고 배열의 새로운 길이를 반환 for (let i = (store.currentPage - 1) * 10; i < store.currentPage * 10; i++) { getList.push(` <li> <a href = '#/show/${news[i].id}'>${news[i].title}(${news[i].comments_count})</a> </li> `); } // end of for getList.push("</ul>"); // 배열의 맨 뒤에 추가하는 함수가 push이다 getList.push("<div>"); // 스타일 추가 고려한 div태그 추가 getList.push( `<a href='#/page/${ store.currentPage > 1 ? store.currentPage - 1 : 1 }'>이전페이지</a>` ); getList.push("  "); // 링크 사이 띄어쓰기 getList.push( `<a href='#/page/${ store.currentPage < 3 ? store.currentPage + 1 : 3 }'>다음페이지</a>` ); getList.push("</div>"); // 빈문자열 주면 구분자 없는 하나의 합쳐진 HTML 문자열을 얻음 container.innerHTML = getList.join(""); // join()은 배열의 모든 요소를 연결해 하나의 문자열로 만듦 } // end of newsList // 뉴스 상세 내용 보기 function newsDetail() { const id = this.location.hash.substring(7); // 상세보기시 앞의 #/show/를 제거하고 가져옴 const newsContent = getData(CONTENT.replace("@id", id)); const h1 = this.document.createElement("h1"); container.innerHTML = ` <h1>${newsContent.title}</h1> <div> <a href = '#/page/${store.currentPage}'>목록으로</a> </div> `; } // end of newDetail // 라우터에서 화면 전환하기 function router() { // 글 목록의 링크는 # -> location.href에 #에왔는데 왜 참인가? // location.href에 #만 들어오면 빈값을 반환 // 그렇기에 이 코드가 작동하는 것 const routePath = location.hash; console.log(routePath); // 첫 진입(첫 요청시)일 때는 해시값이 없으니까 newsList를 호출한다 if (routePath === "") { newsList(); } else if (routePath.indexOf("#/page/") >= 0) { // 해시값 중에서 숫자값만 추출하기 // #/page/를 제거하고 문자열을 숫자로 바꿔야함 store.currentPage = Number(routePath.substring(7)); newsList(); } else { newsDetail(); } } // end of router window.addEventListener("hashchange", router); router();

<step 1>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>클론코딩 - step1[mostPopular]</title> <link rel="stylesheet" href="./youtube.css" /> <script defer src="./youtube.js"></script> </head> <body> <h3>유튜브 클론코딩 실습 1</h3> <div id="root"></div> </body> </html>
const ajax = new XMLHttpRequest(); let content = ""; const key = ""; const MOST_URL = `https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&key=${key}`; ajax.open("GET", MOST_URL, false); ajax.send(); const most = JSON.parse(ajax.response); const items = most.items; console.log(items); console.log(items.length); // 25 content += `<ul class = "videos">`; // 25번 반복 - 25개의 li for (let i = 0; i < items.length; i++) { content += `<li class="container">`; content += `<div class="video">`; content += `<img class = "thumbnail" src='${items[i].snippet.thumbnails.medium.url}' />`; content += `<div">`; content += `<p class = "title">${items[i].snippet.title}</p>`; content += `<p class = "channelTitle">${items[i].snippet.channelTitle}</p>`; content += `</div">`; content += `</div">`; content += `</li">`; } content += `</ul>`; document.querySelector("#root").innerHTML = content;
* { box-sizing: border-box; /* border: 1px solid red; */ } .videos { display: grid; grid-template-columns: 1fr 1fr 1fr; list-style: none; padding-left: 0px; margin: 0; gap: 14px; } .container { width: 100%; padding: 0.2em; } .video { width: 100%; height: 100%; display: flex; align-items: center; border: 1px solid lightgray; box-shadow: 3px 3px 5px 0px rgb(185, 185, 185); transition: transform 250ms ease-in; cursor: pointer; } .video:hover { transform: scale(1.02); } .thumbnail { width: 40%; height: 100%; } .title, .channelTitle { margin: 10px; font-size: 0.8rem; } .channelTitle { font-size: 0.6rem; }
자바는 구조지향적
main을 어디에 넣든 먼저 실행됨
html은 절차지향적
그렇기에 javascript에 defer 넣어줌(html 태그를 모두 읽고 나서 js 적용하기 위해)
<step 2>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>클론코딩 - step2[mostPopular]</title> <link rel="stylesheet" href="./youtube.css" /> <script defer src="./youtube.js"></script> </head> <body> <h3>유튜브 클론코딩 실습 2</h3> <div id="root"></div> </body> </html> <!-- 실습제목: 문자열을 배열로 바꾸어 처리하기 let content = ""; const videoList = []; -->
const ajax = new XMLHttpRequest(); const videoList = []; const key = ""; const MOST_URL = `https://youtube.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&key=${key}`; ajax.open("GET", MOST_URL, false); ajax.send(); const most = JSON.parse(ajax.response); const items = most.items; console.log(items); console.log(items.length); // 25 // push()는 배열의 끝에 요소를 추가하고 배열의 새로운 길이를 반환함 videoList.push(`<ul class = "videos">`); // 25번 반복 - 25개의 li for (let i = 0; i < items.length; i++) { videoList.push(`<li class="container">`); videoList.push(`<div class="video">`); videoList.push( `<img class = "thumbnail" src='${items[i].snippet.thumbnails.medium.url}' />` ); videoList.push(`<div">`); videoList.push(`<p class = "title">${items[i].snippet.title}</p>`); videoList.push( `<p class = "channelTitle">${items[i].snippet.channelTitle}</p>` ); videoList.push(`</div">`); videoList.push(`</div">`); videoList.push(`</li">`); } videoList.push(`</ul>`); // join()은 배열의 모든 요소를 연결해 하나의 문자열로 만듦 // ()기본은 , / ("")은 공백 / ("-")은 - document.querySelector("#root").innerHTML = videoList.join("");
* { box-sizing: border-box; /* border: 1px solid red; */ } .videos { display: grid; grid-template-columns: 1fr 1fr 1fr; list-style: none; padding-left: 0px; margin: 0; gap: 14px; } .container { width: 100%; padding: 0.2em; } .video { width: 100%; height: 100%; display: flex; align-items: center; border: 1px solid lightgray; box-shadow: 3px 3px 5px 0px rgb(185, 185, 185); transition: transform 250ms ease-in; cursor: pointer; } .video:hover { transform: scale(1.02); } .thumbnail { width: 40%; height: 100%; } .title, .channelTitle { margin: 10px; font-size: 0.8rem; } .channelTitle { font-size: 0.6rem; }
<step 3>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>클론코딩 - step3[search-검색기]</title> <link rel="stylesheet" href="./youtube.css" /> <link rel="shortcut icon" href="../../../images/youtube/logo.ico" type="image/x-icon" /> <script defer src="./youtube.js"></script> </head> <body> <h3>유튜브 클론코딩 실습 3</h3> <header class="header"> <div class="logo"> <img src="../../../images/youtube/logo.png" alt="logo" /> <h1 class="headerTitle">Youtube</h1> </div> <!-- name은 자바에서 id는 자바스크립트에서 쓸 예정 --> <input class="input" type="search" name="keyword" id="keyword" placeholder="Search" /> <button class="btnSearch"> <img class="imgSearch" src="../../../images/youtube/search.png" alt="search" /> </button> </header> <div id="root"></div> </body> </html> <!-- 검색기 붙여보기 패비콘(favicon) 이미지 붙이기 배열 - 내장함수(prototype) -->
const keyword = document.querySelector("#keyword"); // input textfield에 입력한 후 엔터쳤을 때를 잡아내는 함수 keyword.addEventListener("keypress", (event) => { console.log("keypress => " + event.keyCode); // 사용자가 입력한 검색어를 찾는 함수 호출 handleSearch(); }); // 사용자가 입력한 검색어 읽어오기 const handleSearch = () => { const user = document.querySelector("#keyword").value; console.log("사용자가 입력한 검색어 => " + user); search(user); }; // 사용자가 입력한 검색어로 조건 검색 구현하기 const search = (query) => { console.log("사용자가 입력한 btns 받음 => " + query); const ajax = new XMLHttpRequest(); const videoList = []; const key = ""; const SEARCH_URL = `https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=30&q=${query}&key=${key}`; ajax.open("GET", SEARCH_URL, false); ajax.send(); const most = JSON.parse(ajax.response); const items = most.items; videoList.push(`<ul class = "videos">`); for (let i = 0; i < items.length; i++) { videoList.push(`<li class="container">`); videoList.push(`<div class="video">`); videoList.push( `<img class = "thumbnail" src='${items[i].snippet.thumbnails.medium.url}' />` ); videoList.push(`<div">`); videoList.push(`<p class = "title">${items[i].snippet.title}</p>`); videoList.push( `<p class = "channelTitle">${items[i].snippet.channelTitle}</p>` ); videoList.push(`</div">`); videoList.push(`</div">`); videoList.push(`</li">`); } videoList.push(`</ul>`); document.querySelector("#root").innerHTML = videoList.join(""); }; // end of search
* { box-sizing: border-box; /* border: 1px solid red; */ } .header { display: flex; height: 4rem; padding: 0.5rem 1rem; margin: 0 0.2rem; background-color: black; } .logo { display: flex; align-items: center; margin-right: 1em; } .headerTitle { color: white; margin: 0.2rem 0.5rem; } .input { flex-basis: 100%; font-size: 1.1rem; outline: 0; margin: 0rem 0.5rem; } .btnSearch { background-color: rgb(223, 50, 50); outline: 0; } .imgSearch { height: 100%; padding: 0.5em 0.2em; } .videos { display: grid; grid-template-columns: 1fr 1fr 1fr; list-style: none; padding-left: 0px; margin: 0; gap: 14px; } .container { width: 100%; padding: 0.2em; } .video { width: 100%; height: 100%; display: flex; align-items: center; border: 1px solid lightgray; box-shadow: 3px 3px 5px 0px rgb(185, 185, 185); transition: transform 250ms ease-in; cursor: pointer; } .video:hover { transform: scale(1.02); } .thumbnail { width: 40%; height: 100%; } .title, .channelTitle { margin: 10px; font-size: 0.8rem; } .channelTitle { font-size: 0.6rem; }
Babel은 Javascript 컴파일러이다
컴파일러(Compiler) 언어 해석기, 특정 언어를 다른 프로그래밍 언어로 옮기는 프로그램
내가 쓴 내용
const element = <h1>Hello, React</h1>
Babel이 바꿔준 내용
"use strict"; // 엄격모드(제약조건 생김) const element = /#PURE/React.createElement("h1", null, "Hello, React");
<React, Babel 예제 1>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>바벨소개</title> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <style> .title { color: green; } </style> <!-- type을 babel로 해야 바닐라스크립트 -> 리액트 섞어쓰기 가능 --> <script type="text/babel"> const rootElement = document.querySelector("#root"); const element = React.createElement( "h1", { className: "title", }, ["Java", "React", "Spring"] ); ReactDOM.createRoot(rootElement).render(element); </script> </body> </html>
<React, Babel 예제 2>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>바벨소개</title> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <style> .title { color: red; } </style> <!-- type을 babel로 해야 바닐라스크립트 -> 리액트 섞어쓰기 가능 --> <script type="text/babel"> const rootElement = document.querySelector("#root"); const element = <h1 className="title">JAVA</h1>; ReactDOM.createRoot(rootElement).render(element); </script> </body> </html>
<React, Babel 예제 3>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>바벨소개</title> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <style> .title { color: purple; font-size: 58px; } </style> <!-- type을 babel로 해야 바닐라스크립트 -> 리액트 섞어쓰기 가능 --> <script type="text/babel"> const rootElement = document.querySelector("#root"); const subject = "React"; const 클래스이름 = "title"; const element = <h1 className={클래스이름}>{subject}</h1>; ReactDOM.createRoot(rootElement).render(element); </script> </body> </html>
<React, Babel 예제 4>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>바벨소개</title> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <style> .title { color: blue; font-size: 58px; } </style> <!-- type을 babel로 해야 바닐라스크립트 -> 리액트 섞어쓰기 가능 --> <script type="text/babel"> const rootElement = document.querySelector("#root"); const subject = "React"; const 클래스이름 = "title"; const 사용자정의태그 = <h1 className={클래스이름}>{subject}</h1>; ReactDOM.createRoot(rootElement).render(사용자정의태그); </script> </body> </html>
<React, Babel 예제 5>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>바벨소개</title> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <style> .title { color: yellow; background-color: blue; font-size: 58px; } </style> <!-- type을 babel로 해야 바닐라스크립트 -> 리액트 섞어쓰기 가능 --> <script type="text/babel"> const rootElement = document.querySelector("#root"); const subject = "React"; const 클래스이름 = "title"; const props = { className: 클래스이름, children: subject }; const 사용자정의태그 = <h1 {...props} />; ReactDOM.createRoot(rootElement).render(사용자정의태그); </script> </body> </html>
<React, Babel 예제 6>
<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>바벨소개</title> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js" ></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> </head> <body> <div id="root"></div> <style> .title { color: pink; background-color: lightgray; font-size: 58px; } </style> <!-- type을 babel로 해야 바닐라스크립트 -> 리액트 섞어쓰기 가능 --> <script type="text/babel"> const rootElement = document.querySelector("#root"); const subject = "React"; const 클래스이름 = "title"; const props = { className: 클래스이름, children: subject }; const 사용자정의태그 = ( <h1 className={props.className} children={props.children}></h1> ); ReactDOM.createRoot(rootElement).render(사용자정의태그); </script> </body> </html>
'국비학원 > 수업기록' 카테고리의 다른 글
국비 지원 개발자 과정_Day53 (1) | 2023.02.13 |
---|---|
국비 지원 개발자 과정_Day52 (1) | 2023.02.10 |
국비 지원 개발자 과정_Day50 (0) | 2023.02.08 |
국비 지원 개발자 과정_Day49 (0) | 2023.02.07 |
국비 지원 개발자 과정_Day48 (0) | 2023.02.04 |
댓글