From ad144261d666480fae0768c48b9c0fa2d7204c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=A2=E1=84=8B?= =?UTF-8?q?=E1=85=AF=E1=86=AB?= Date: Fri, 27 Dec 2024 23:19:02 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat(nav,=20dummydata,=20nvigate):=20?= =?UTF-8?q?=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20ui=20,=20?= =?UTF-8?q?=EB=8D=94=EB=AF=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20,=20history=20api=EB=A1=9C=20routing=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- app.js | 43 +++++++++++++++++++++++++++++++++++++++++++ index.html | 26 ++++++++++++++++++++++++++ main.html | 11 ----------- posts.json | 8 ++++++++ style.css | 27 +++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 app.js create mode 100644 index.html delete mode 100644 main.html create mode 100644 posts.json create mode 100644 style.css diff --git a/README.md b/README.md index c45a868..f75b74e 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# SPA-project \ No newline at end of file +# SPA-project diff --git a/app.js b/app.js new file mode 100644 index 0000000..ec672c1 --- /dev/null +++ b/app.js @@ -0,0 +1,43 @@ +// 데이터 가져오기 +let data = []; + +async function fetchData() { + const response = await fetch('/posts.json'); + data = await response.json(); + console.log(data); + + renderPage('/'); +} + +function renderPage(route) { + const app = document.getElementById('app'); + let filteredData; + + if (route === '/') { + filteredData = data; + } else { + filteredData = data.filter( + (item) => item.category === route.replace('/', '') + ); + } + + app.innerHTML = ` + + `; +} + +function navigate(url) { + history.pushState(null, null, url); + renderPage(url); +} + +document.addEventListener('click', (e) => { + if (e.target.matches('[data-link]')) { + e.preventDefault(); + navigate(e.target.getAttribute('href')); + } +}); + +fetchData(); diff --git a/index.html b/index.html new file mode 100644 index 0000000..4dd2ea0 --- /dev/null +++ b/index.html @@ -0,0 +1,26 @@ + + + + + + SPA-Project main + + + + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/main.html b/main.html deleted file mode 100644 index 55ead72..0000000 --- a/main.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - SPA-Project main - - - - - \ No newline at end of file diff --git a/posts.json b/posts.json new file mode 100644 index 0000000..256a31d --- /dev/null +++ b/posts.json @@ -0,0 +1,8 @@ +[ + { "id": 1, "category": "develop", "title": "JavaScript 기초" }, + { "id": 2, "category": "develop", "title": "React Hooks 소개" }, + { "id": 3, "category": "design", "title": "UI/UX 디자인 가이드" }, + { "id": 4, "category": "design", "title": "Figma 사용법" }, + { "id": 5, "category": "develop", "title": "프로젝트 계획 수립" }, + { "id": 6, "category": "develop", "title": "협업 도구 소개" } + ] \ No newline at end of file diff --git a/style.css b/style.css new file mode 100644 index 0000000..875c460 --- /dev/null +++ b/style.css @@ -0,0 +1,27 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + padding: 0; +} + +nav { + display: flex; + background: #333; + padding: 10px; +} + +nav a { + color: white; + text-decoration: none; + padding: 10px 20px; + margin-right: 10px; +} + +nav a.active { + background: #555; + border-radius: 5px; +} + +#app { + padding: 20px; +} From eb5e877bb77c0d9b7456b593901f5e0da068a8fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=A2=E1=84=8B?= =?UTF-8?q?=E1=85=AF=E1=86=AB?= Date: Sun, 29 Dec 2024 15:21:11 +0900 Subject: [PATCH 02/10] =?UTF-8?q?feat(popState,=20detailPage):=20=EB=92=A4?= =?UTF-8?q?=EB=A1=9C=EA=B0=80=EA=B8=B0=20=EC=95=9E=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=EA=B0=80=EA=B8=B0=20=EC=B6=94=EA=B0=80,=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=EB=B3=B4=EA=B8=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 45 +++++++++++++++++++++++++++++++++++---------- index.html | 1 - posts.json | 14 +++++++------- style.css | 5 +++++ 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/app.js b/app.js index ec672c1..dd678cb 100644 --- a/app.js +++ b/app.js @@ -4,39 +4,64 @@ let data = []; async function fetchData() { const response = await fetch('/posts.json'); data = await response.json(); - console.log(data); - renderPage('/'); } function renderPage(route) { const app = document.getElementById('app'); let filteredData; - + // 라우트가 메인페이지일떄 if (route === '/') { filteredData = data; + app.innerHTML = ` + + `; + // 라우트가 detail일떄 + } else if (route.startsWith('/detail')) { + const id = route.split('/')[2]; + const item = data.find((item) => item.id == id); + // 라우트가 detail 일치하는 id 가있을떄 + if (item) { + app.innerHTML = ` +

${item.title}

+

${item.content}

+ `; + } + // 라우트가 develop, design일때 } else { filteredData = data.filter( (item) => item.category === route.replace('/', '') ); - } - - app.innerHTML = ` + app.innerHTML = ` `; + } } -function navigate(url) { - history.pushState(null, null, url); +function navigate(url, state = {}) { + history.pushState(state, null, url); renderPage(url); } document.addEventListener('click', (e) => { if (e.target.matches('[data-link]')) { e.preventDefault(); - navigate(e.target.getAttribute('href')); + const url = e.target.getAttribute('href'); + console.log('url', url); + const state = { id: url.split('/')[2] }; + navigate(url, state); + } +}); + +window.addEventListener('popstate', (e) => { + console.log('e', e); + if (e.state) { + console.log('e.state', e.state); + renderPage(location.pathname); } }); diff --git a/index.html b/index.html index 4dd2ea0..c31d5e4 100644 --- a/index.html +++ b/index.html @@ -16,7 +16,6 @@ 전체 개발 디자인 -
diff --git a/posts.json b/posts.json index 256a31d..a6e9ac7 100644 --- a/posts.json +++ b/posts.json @@ -1,8 +1,8 @@ [ - { "id": 1, "category": "develop", "title": "JavaScript 기초" }, - { "id": 2, "category": "develop", "title": "React Hooks 소개" }, - { "id": 3, "category": "design", "title": "UI/UX 디자인 가이드" }, - { "id": 4, "category": "design", "title": "Figma 사용법" }, - { "id": 5, "category": "develop", "title": "프로젝트 계획 수립" }, - { "id": 6, "category": "develop", "title": "협업 도구 소개" } - ] \ No newline at end of file + { "id": 1, "category": "develop", "title": "JavaScript 기초", "content": "자바스크립트 기초 컨텐츠"}, + { "id": 2, "category": "develop", "title": "React Hooks 소개", "content": "React Hooks 소개" }, + { "id": 3, "category": "design", "title": "UI/UX 디자인 가이드" , "content": "UI/UX 디자인 가이드"}, + { "id": 4, "category": "design", "title": "Figma 사용법", "content": "Figma 사용법" }, + { "id": 5, "category": "develop", "title": "프로젝트 계획 수립", "content": "프로젝트 계획 수립"}, + { "id": 6, "category": "develop", "title": "협업 도구 소개" , "content": "협업 도구 소개"} +] \ No newline at end of file diff --git a/style.css b/style.css index 875c460..afa8db3 100644 --- a/style.css +++ b/style.css @@ -25,3 +25,8 @@ nav a.active { #app { padding: 20px; } + +#app a { + text-decoration: none; + color: black; +} From ffb550a6c94d67b541cc47110f655ccd2928f041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=A2=E1=84=8B?= =?UTF-8?q?=E1=85=AF=E1=86=AB?= Date: Mon, 30 Dec 2024 02:22:29 +0900 Subject: [PATCH 03/10] refactoring --- app.js | 76 ++++++++------------------------------------------ dataservice.js | 14 ++++++++++ index.html | 21 ++++++-------- navbar.js | 17 +++++++++++ router.js | 44 +++++++++++++++++++++++++++++ settings.json | 11 ++++++++ 6 files changed, 106 insertions(+), 77 deletions(-) create mode 100644 dataservice.js create mode 100644 navbar.js create mode 100644 router.js create mode 100644 settings.json diff --git a/app.js b/app.js index dd678cb..a8f4a0d 100644 --- a/app.js +++ b/app.js @@ -1,68 +1,14 @@ -// 데이터 가져오기 -let data = []; - -async function fetchData() { - const response = await fetch('/posts.json'); - data = await response.json(); - renderPage('/'); -} - -function renderPage(route) { - const app = document.getElementById('app'); - let filteredData; - // 라우트가 메인페이지일떄 - if (route === '/') { - filteredData = data; - app.innerHTML = ` - - `; - // 라우트가 detail일떄 - } else if (route.startsWith('/detail')) { - const id = route.split('/')[2]; - const item = data.find((item) => item.id == id); - // 라우트가 detail 일치하는 id 가있을떄 - if (item) { - app.innerHTML = ` -

${item.title}

-

${item.content}

- `; - } - // 라우트가 develop, design일때 - } else { - filteredData = data.filter( - (item) => item.category === route.replace('/', '') - ); - app.innerHTML = ` - - `; +import { setupRouter } from './router.js'; +import { setNavEvent } from './navbar.js'; + +// 초기화함수 +async function initApp() { + try { + setNavEvent(); + setupRouter(); + } catch (error) { + console.error('초기화 에러', error); } } -function navigate(url, state = {}) { - history.pushState(state, null, url); - renderPage(url); -} - -document.addEventListener('click', (e) => { - if (e.target.matches('[data-link]')) { - e.preventDefault(); - const url = e.target.getAttribute('href'); - console.log('url', url); - const state = { id: url.split('/')[2] }; - navigate(url, state); - } -}); - -window.addEventListener('popstate', (e) => { - console.log('e', e); - if (e.state) { - console.log('e.state', e.state); - renderPage(location.pathname); - } -}); - -fetchData(); +initApp(); diff --git a/dataservice.js b/dataservice.js new file mode 100644 index 0000000..8da206d --- /dev/null +++ b/dataservice.js @@ -0,0 +1,14 @@ +export async function fetchAllData() { + const response = await fetch('/posts.json'); + return await response.json(); +} + +export async function fetchCategoryData(category) { + const response = await fetchAllData(); + return response.filter((item) => item.category === category); +} + +export async function fetchDetailData(id) { + const response = await fetchAllData(); + return response.find((item) => item.id == id); +} diff --git a/index.html b/index.html index c31d5e4..4602508 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + @@ -7,19 +7,16 @@ - - - - - - +
+ +
- + \ No newline at end of file diff --git a/navbar.js b/navbar.js new file mode 100644 index 0000000..cae0e7a --- /dev/null +++ b/navbar.js @@ -0,0 +1,17 @@ +export function setNavEvent() { + const navbar = document.getElementById('navbar'); + + navbar.addEventListener('click', (e) => { + if (e.target.tagName === 'A' && e.target.hasAttribute('data-link')) { + console.log('이벤ㄴ트되네?'); + e.preventDefault(); + const url = e.target.getAttribute('href'); + navigate(url); + } + }); + + function navigate(url) { + history.pushState(null, null, url); + window.dispatchEvent(new PopStateEvent('popstate')); + } +} diff --git a/router.js b/router.js new file mode 100644 index 0000000..9ed3bac --- /dev/null +++ b/router.js @@ -0,0 +1,44 @@ +import { + fetchCategoryData, + fetchDetailData, + fetchAllData, +} from './dataservice.js'; + +async function renderPage(route) { + const app = document.getElementById('app'); + let content = ''; + + if (route === '/') { + // 전체 페이지 + const data = await fetchAllData(); // 전체 데이터 요청 + content = ` + + `; + } else if (route.startsWith('/develop') || route.startsWith('/design')) { + // 카테고리 페이지 + const category = route.replace('/', ''); + const data = await fetchCategoryData(category); + content = ` + + `; + } else if (route.startsWith('/detail/')) { + // 상세 페이지 + const id = route.split('/')[2]; + const item = await fetchDetailData(id); + content = `

${item.title}

${item.content}

`; + } + + app.innerHTML = content; +} + +export function setupRouter() { + renderPage(location.pathname); + + window.addEventListener('popstate', () => { + renderPage(location.pathname); + }); +} diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..1ba92bd --- /dev/null +++ b/settings.json @@ -0,0 +1,11 @@ +{ + "liveServer.settings.root": "/", + "liveServer.settings.port": 8080, + "liveServer.settings.rewriteRules": [ + { + "source": ".*", // 모든 경로에 적용 + "destination": "/index.html" // 항상 index.html로 리디렉션 + } + ] + } + \ No newline at end of file From 16f1893927c0896f1b07e437ec731e2578d9599b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=A2=E1=84=8B?= =?UTF-8?q?=E1=85=AF=E1=86=AB?= Date: Mon, 30 Dec 2024 21:36:08 +0900 Subject: [PATCH 04/10] =?UTF-8?q?refactor/separation=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=97=AD=ED=95=A0=20=EB=B6=84=EB=A6=AC=20=EC=B6=94=EC=83=81?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- navbar.js | 5 +---- router.js | 1 + settings.json | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/navbar.js b/navbar.js index cae0e7a..0ff77a4 100644 --- a/navbar.js +++ b/navbar.js @@ -1,9 +1,6 @@ export function setNavEvent() { - const navbar = document.getElementById('navbar'); - - navbar.addEventListener('click', (e) => { + document.addEventListener('click', (e) => { if (e.target.tagName === 'A' && e.target.hasAttribute('data-link')) { - console.log('이벤ㄴ트되네?'); e.preventDefault(); const url = e.target.getAttribute('href'); navigate(url); diff --git a/router.js b/router.js index 9ed3bac..605640e 100644 --- a/router.js +++ b/router.js @@ -28,6 +28,7 @@ async function renderPage(route) { } else if (route.startsWith('/detail/')) { // 상세 페이지 const id = route.split('/')[2]; + console.log('id', id); const item = await fetchDetailData(id); content = `

${item.title}

${item.content}

`; } diff --git a/settings.json b/settings.json index 1ba92bd..0d1939a 100644 --- a/settings.json +++ b/settings.json @@ -3,8 +3,8 @@ "liveServer.settings.port": 8080, "liveServer.settings.rewriteRules": [ { - "source": ".*", // 모든 경로에 적용 - "destination": "/index.html" // 항상 index.html로 리디렉션 + "source": ".*", + "destination": "/index.html" } ] } From a4cc5932cdd49e5691505ba8c5bafe433718cb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=86=B7=E1=84=8C=E1=85=A2=E1=84=8B?= =?UTF-8?q?=E1=85=AF=E1=86=AB?= Date: Mon, 30 Dec 2024 21:36:08 +0900 Subject: [PATCH 05/10] =?UTF-8?q?cherry=20pick=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 4602508..fc4328f 100644 --- a/index.html +++ b/index.html @@ -5,8 +5,10 @@ SPA-Project main + +