2022. 6. 1. 22:57ใFront-End ์์ ์ค/Nuxt.js
Git Hub
๐ ๋ชฉ์ฐจ
โ [Vue+Nuxt.js] Nuxt.js ๊ธฐ๋ณธ
โ[Vue+Nuxt.js] Nuxt.js ์์ํ๊ธฐ
โ [Vue+Nuxt.js] Nuxt.js Data ํธ์ถ ๋ฐฉ์๊ณผ API ์ฐ๋
โ[Vue+Nuxt.js] Nuxt.js๋ฅผ ์ด์ฉํ์ฌ ์ผํ ์ํ ๋ชฉ๋ก ํ์ด์ง์ ์์ธ ํ์ด์ง ๊ฐ๋ฐ
โ [Vue+Nuxt.js] Nuxt.js๋ฅผ ์ด์ฉํ์ฌ ์ผํ ์ํ ๊ฒ์ UI ๊ฐ๋ฐ
โ[Vue+Nuxt.js] Vuex๋ฅผ ์ด์ฉํ์ฌ ์ฅ๋ฐ๊ตฌ๋ Page ๋ง๋ค๊ธฐ
โ [Vue+Nuxt.js] Vuex ์๋ก๊ณ ์นจ ์ ์ด๊ธฐํ ๋๋ ๋ฌธ์ ํด๊ฒฐ
๐ ๋ถ๋ก
โ [FrontEnd] HMR(Hot Module Replacement)
โ [Nuxt.js] ๋น๋๊ธฐ ๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ๋ฒ
โ V-Model ๋์ ์๋ฆฌ์ ํ์ฉ ๋ฐฉ๋ฒ
โ [Nuxt.js] NuxtServerInit
๐ ๋ด๊ฐ ๋ง๋ Error
โ [vuex] expects string as the type, but found undefined.
๐ ์ผํ ์ํ ๊ฒ์ UI ๊ฐ๋ฐ
๐ฝ ๊ฒ์ UI ์ปดํฌ๋ํธํ
์ต์ด ๊ฒ์์ด๋ผ๋ ๊ธฐ๋ฅ์ ์ด๋์๋ ์ง ์ฌ์ฉ๋ ์ ์๋ ๊ณตํต component๋ก ๋ง๋ค์ด ์ฃผ๋ ๊ฒ์ด ์ข๊ธฐ ๋๋ฌธ์ /components ๋ฐ์ SearchInput.vue๋ฅผ ๋ง๋ค์ด ์ฃผ๋๋ก ํ ๊ฒ์.
๊ทธ๋ฆฌ๊ณ , /pages/index.vue์๋ ๊ฒ์์ ์ํด ๋ฃ์ด์คฌ์๋ Input Tag๊ฐ ์๋๋ฐ, ์ด ๊ฒ์ ์ง์ฐ๊ณ , ์์์ ๋ง๋ Component๊ฐ ๋ถ๋๋ก ์์ ์ ํด ์ค ๊ฒ์ด์์.
์ฐธ๊ณ ๋ก 4๋ฒ์งธ ์ค์ <SerchInput์ ์
๋ ฅํ๊ณ , Tab์ ๋๋ฅด๊ฒ ๋๋ฉด ์๋์ผ๋ก 19๋ฒ์งธ ์ค์ฒ๋ผ import๊ฐ ๋ ๊ฒ์ด๊ณ , 22๋ฒ์งธ ์ค์ฒ๋ผ Component๊ฐ ๋ฑ๋ก๋ ๊ฒ์ด์์.
ํด๋น Component์์ ๊ฒ์ ์์ ๋ฐ์ ๊ฒ์์ด๊ฐ /pages/index.vue์ ์ฐ๋๋๊ฒ ์์
์ ํด์ผ ํด์.
์์ ์ฝ๋ ์ค 5 ~ 6์ 7๋ฒ์งธ ์ค์ด ํตํฉ ํ๋ ๊ณผ์ ์ ๊ธฐ์ตํ๊ธฐ ์ํด ์ง์ฐ์ง ์์ ๋ถ๋ถ ์ ๋๋ค. ์์ด์ ธ๋ ๋๋ ์ฝ๋ ์ด๋ ์ฐธ๊ณ ๋ถํ ๋๋ฆฝ๋๋ค.
๋จผ์ V-Model์ ๋ํด์ `์ด ๊ณณ`์ ๋ด์ฉ์ ์ค๋น ํด ๋์์ด์.
์ต์ด ์ด์ฉ์๊ฐ ๊ฒ์์ด๋ฅผ ์
๋ ฅํ๊ฒ ๋๋ฉด 13๋ฒ์งธ ์ค props๋ก ๋ฐ์ value๋ฅผ Input Tag์ ๊ฐ์ผ๋ก ์ฐ๊ฒฐ์ ํฉ๋๋ค.
Input Tag์ ๊ฐ์ด ์
๋ ฅ๋๋ฉด Input Tag์์ input Event๊ฐ ๋ฐ์ํ๊ฒ ๋๊ณ , 5๋ฒ์งธ ์ค์ @input์ผ๋ก ์ปดํฌ๋ํธ ๊ฐ Data ๊ณต์ ๋ฅผ ์ ์ธํ๊ณ , $emit์ ํตํด ๋ถ๋ชจ Component์ธ index.vue์ ํด๋น Event์ value๋ฅผ ์ ๋ฌ ํด ์ฃผ๋ ๊ฒ์ด์์.
ํด๋น value๋ 60๋ฒ์งธ ์ค์ updateSearchKeyword์ ๋งค๊ฐ ๋ณ์๋ก ์ ๋ฌ๋๊ฒ ๋๊ณ , 61๋ฒ์งธ ์ค์ this.searchKeyword๋ฅผ ํตํด
50๋ฒ์งธ ์ค์ serachKeyword์ ๊ฐ์ด ๋ค์ด๊ฐ๊ฒ ๋ ๊ฒ์ด์์.
์ด๋ฐ ๋ฐฉ์์ผ๋ก ๊ฒ์์ด์ ๋ํ Data๋ฅผ Component ๊ฐ ๊ณต์ ๋ฅผ ํ๋๋ก ํด ์ฃผ์์ต๋๋ค.
๐ฝ ๊ฒ์์ ์ํ API ํจ์ ์ค๊ณ ๋ฐ ๊ตฌํ
๊ฒ์์ ํ ์ค๋น๊ฐ ๋์์ผ๋ ์ด ๊ฒ์์ด๋ฅผ Back End์ ๋ณด๋ด์ ํด๋น ๊ฒ์์ ๋ง๋ ๋ด์ฉ์ ๊ฐ์ ธ์ค๋ ์ฒ๋ฆฌ๋ฅผ ํด ์ฃผ์ด์ผ ํด์.
๋จผ์ ๊ฒ์์ด ๊ธฐ๋ฅ์ ๋ด๋นํ๋ Component์ธ SearchInput.vue์ 7๋ฒ์งธ ์ค์ฒ๋ผ Click Event๊ฐ ๋ฐ์ํ๋ฉด $emit์ ํตํด ์์ Component์ search Event๋ฅผ ์ ๋ฌํ๋๋ก ๋ง๋ค์ด ์ฃผ์์ด์.
๊ทธ๋ผ ๋ค์ index.vue์์ 4๋ฒ์งธ ์ค์ ๋ณด๋ฉด @search="searchProducts"๋ฅผ ์ถ๊ฐ ํด ์ฃผ์๋๋ฐ, ์ด ๋ถ๋ถ์ด ๋ฐ๋ก ํ์ Component SearchInput.vue 7๋ฒ์งธ ์ค์์ ๋ฐ์ํ Click Event๋ฅผ ๋ฐ๋ ๊ณณ์ด์์. Click Event๊ฐ ๋ฐ์ํ๊ฒ ๋๋ฉด searchProducts๋ผ๋ ํจ์๊ฐ ํธ์ถ ๋๊ฒ ๋ฉ๋๋ค.
์ด ๊ณณ์์ ์ฐ๋ฆฌ๊ฐ ์ฃผ๋ชฉํด์ผ ํ ๊ณณ์ 57 ~ 62๋ฒ์ฌ ์ค ๊น์ง์์. ์์์ Click Event๊ฐ ๋ฐ์ํ๋ฉด ๋ฐ๋ก ์ด Method๊ฐ ํธ์ถ ๋๊ฒ ๋๋๋ฐ, 59๋ฒ์งธ ์ค์ ๋ณด๋ฉด fetchProductsByKeyword()๋ฅผ ํธ์ถํ๋ฉด์ ๊ฒ์์ด๋ฅผ ๋ด์ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํด ์ฃผ๊ณ ์๋ ๊ฒ์ด์์.
๐ฆ API ํจ์ ์ค๊ณ
fetchProductsByKeyword()๋ /api Package๋ฅผ ๋ณด๋ฉด index.js๊ฐ ์์ํ
๋ฐ ๊ทธ ๊ณณ์ ์ ์ํ์ฌ Moduleํ ํด ์ฃผ์์ต๋๋ค. ์ด ๊ณณ์์ axios๋ฅผ ์ด์ฉํ API ํต์ ํจ์๋ฅผ ๋ง๋ค์ด ์ค ๊ฑฐ์์.
์ฐ๋ฆฌ๋ ์ด๋ฐ์์ผ๋ก Query String ๋ฐฉ์์ ์ด์ฉํ API๋ฅผ ์ค๊ณํ ์๋ ์์ด์. ํ์ง๋ง ์ด๋ ๊ฒ ํ ํ์๊ฐ ์๋๋ฐ, ์ผ๋จ ์ด๋ ๊ฒ ๋๋ฉด Query String์ ๋งค ๋ฒ ๋ถ์ฌ์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์๊ธฐ๊ฒ ๋๋ ๊ฒ์ด์์.
๊ทธ๋์ ์์ ๊ฐ์ด config์ params ์์ฑ ์ด์ฉํ์ฌ ๊ฐ์ฒด๋ฅผ ๋ณด๋ด๋ฒ๋ฆฌ๋ ๋ฐฉ์์ ๊ตฌํํ๋ ๊ฒ์ด ๊ฐ๋ ์ฑ ๋ฑ ๋ฉด์์ ์ข๋ต๋๋ค.
๋ค์ index.vue์ searchProducts()๋ฅผ ๋ณด๋ฉด ์ API๋ฅผ ํตํด ๋ฐ์์จ Data๋ฅผ ์์ํ ๋ณ์ response์ ๋ด์์ฃผ๊ฒ ๋์. ๊ทธ๋ฐ ๋ค์ ์ด Data ๊ฐ์ ์ถ๋ ฅํด ๋ณด๊ฒ ๋๋ฉด
์ผ๋จ์ ๊ฒ์์ด์ 'chicken'์ ์
๋ ฅ ํด ์ฃผ์๊ณ , ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ํตํด ์ฝ์ ์ถ๋ ฅ์ ํ์ธํด ๋ณด๋ฉด 3๊ฐ์ ๋ฐฐ์ด์ด ์๋ต ๋ ๊ฒ์ ๋ณผ ์ ์์ด์.
name์ ๋ณด๋ chicken์ด๋ผ๋ ๋จ์ด๊ฐ ๋ค์ด๊ฐ ๋ด์ฉ๋ค์ ๊ฒ์ํด ์จ ๊ฒ์ ํ์ธํ ์๊ฐ ์์ด์!
๐ฝ ๊ฒ์ ๊ธฐ๋ฅ ๋ง๋ฌด๋ฆฌ
๐ฆ serchProducts()
๊ณ์ํด์ ์ฐ๋ฆฌ๋ serchProducts()๋ฅผ ์ ์ฌํ ์ง์ผ๋ณผ ๊ฒ์ด์์.
์ด๋ฒ์ ์ถ๊ฐ๋ ๋ด์ฉ์ 65~68๋ฒ์งธ ์ค ๊น์ง์์.
์ค๋ช
ํ๊ธฐ์ ์ ์จ ์ฐ๋ฆฌ๋ asyncData()๋ฅผ ํตํด products๋ผ๋ ์์ํ ๋ณ์๋ฅผ ๋ง๋ค์ด ์ค ์ ์ด ์์ด์.
ํด๋น ๋ด์ฉ์ ๋ชป ๋ณด๊ณ ์ค์ ๋ถ๋ค์ '์ด ๊ณณ'์์ ๋ง๋์ค ์ ์๊ฒ ์ค๋น ํด ๋์์ต๋๋ค!
ํ์ฌ data()์๋ products๋ผ๋ ์น๊ตฌ๊ฐ ์กด์ฌํ์ง ์์ง๋ง,
asyncData()์ return ํ ๊ฐ์ด Vue Data()์ ์์ฑ์ผ๋ก ์ ์ ๋ฐ ์ค์ ์ด ๋๋ ์ ์ ์ฐ๋ฆฌ๊ฐ ๊ผญ ๊ธฐ์ตํด ๋์ด์ผ ํ๋ ๊ฒ์ด์์. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ products๋ ํด๋น ์ธ์คํด์ค(๊ฐ์ฒด)์ Data() ์์ฑ์ผ๋ก ์กด์ฌํ๊ณ ์๋ต๋๋ค.
์ด๋ ๊ฒ ํ๊ณ ๋๋ฉด ์์ ๊ฐ์ด ๊ฒ์์ด๋ฅผ ์
๋ ฅํ์ ๋, ํด๋น ๊ฐ์ ํด๋นํ๋ ๋ด์ฉ๋ง ๋ถ๋ฌ์ค๋ ๊ฒ์ ํ์ธํ ์ ์์ด์.
ํ์ฌ Back End๋ FE๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ์์์ ์ธ Server์ด๊ธฐ ๋๋ฌธ์ ์ฌ์ง์ด Chicken๊ณผ๋ ๋ง์ง ์๋๋ค๋ ์ ์ ๊ผญ ์ฐธ๊ณ ๋ถํ๋๋ฆฝ๋๋ค.
๐ฝ Header์ ๊ฒ์ UI Style ์ ๋ฆฌ
๐ฆ defulat.vue
์ต์ด Header๋ถ๋ถ์ ๋ํ CSS ์ฒ๋ฆฌ๋ฅผ ํด ๋ณด๋๋ก ํ ๊ฒ์.
Header์ ๋ํ ๋ด์ฉ์ /layouts/default.vue์ ์์นํ๊ณ ์์ด์.
๊ณตํต์ Style์ ๊พธ๋ฏธ๋ ค๊ณ ํ ๋ layouts Package ๋ฐ์ vue File์ ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค๊ณ ์ฐ๋ฆฌ๋ ๊ณต๋ถ๋ฅผ ํ์์ด์.
Header๋ผ๋ ์น๊ตฌ๋ ์ด๋ Page์๋ ๊ณตํต์ผ๋ก ๋์์ผ ํ๋ ๋ถ๋ถ์ด๊ธฐ ๋๋ฌธ์ ์ Package์ ๋ง๋ค์ด ์ฃผ์์ด์.
์ต์ด header์ class๋ฅผ title๋ก ํ๊ณ , 16 ~ 20๋ฒ์งธ๊น์ง ํด๋น ๋ด์ฉ์ ๋ํ CSS๋ฌธ์ ์์ฑํด ์ฃผ์์ด์.
๊ทธ๋ฆฌ๊ณ , NuxtLink์ class๋ฅผ logo๋ผ๊ณ ์ ์ํ๊ณ , 22๋ฒ์งธ ~ 27๋ฒ์งธ๊น์ง ํด๋น Class ์ด๋ฆ๊ณผ Matching๋๋ CSS๋ฌธ์ ์์ฑํด ์ฃผ์์ต๋๋ค.
๐ฆ SerchInput.vue
์ด๋ฒ์๋ ๊ฒ์์ ๋ํ Input Box์ Button์ ๊พธ๋ฉฐ๋ณผ๊ฒ์.
์ต์ด 2๋ฒ์งธ ์ค์ dIv Tag์ class๋ฅผ input-wrapper๋ก ์ง์ด์ฃผ๊ณ , 5๋ฒ์งธ ์ค์ input Tag์ class๋ฅผ search-input์ด๋ผ๊ณ ์ด๋ฆ ์ง์ด ์ฃผ์์ด์.
๊ทธ๋ฆฌ๊ณ , 8๋ฒ์งธ ์ค์ button Tag class๋ฅผ btn์ด๋ผ๊ณ ์ด๋ฆ ์ง์ด ์ฃผ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค ์์ ๊ฐ์ด CSS๋ฌธ์ ์ ๋ ฅํ์ฌ ๊พธ๋ฉฐ ์ฃผ์์ด์. ์ฐธ๊ณ ๋ก .์ด ๋ถ์ ๊ฒ์ class ์ด๋ฆ๊ณผ Matching์ด ๋๊ณ , .์ด ๋ถ์ง ์์ ๊ฒ์ ID ์ด๋ฆ๊ณผ Matching์ด ๋๋ต๋๋ค. ํด๋น ๋ด์ฉ์ ๋ํด ์ ๋ชจ๋ฅด๊ฒ ๋ ๋ถ๋ค์ ์ํด '์ด ๊ณณ'์ ์ ๋ฆฌ ํด ๋์์ด์!
๋ํ, Style Tag์ scoped๋ผ๊ณ ๋ถ๋ ๊ฒ์ ํด๋น vue File์์๋ง ์ ์ฉ๋๊ฒ ํ๊ธฐ ์ํจ์ด์์.
์ฆ, Vue๋ฅผ ์ฌ์ฉํ๋ ํ๋ก์ ํธ๋ ๋ค์์ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ํ๋์ ์ฑ์ ๊ตฌํํ๊ฒ ๋ฉ๋๋ค. ์ด ๊ฒฝ์ฐ ๊ฐ๊ฐ์ ์ปดํฌ๋ํธ์ ์ ์ธ๋ ์คํ์ผ์ด ์๋ํ์ง ์๊ฑฐ๋ ์ค์์ ์ํ์ฌ ๋ค๋ฅธ ์ปดํฌ๋ํธ์ ์ํฅ์ ์ค ์ ์์ ์ ์๋ ๊ฒ์ด์์. ์ด์ฒ๋ผ ์ค์ง ํน์ ์ปดํฌ๋ํธ์๋ง ๊ณ ์ ์ ์คํ์ผ์ ์ ์ธํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ผ๋ก vue-loader๊ฐ ์ ๊ณตํ๋ scoped ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
'Front-End ์์ ์ค > Nuxt.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Nuxt.js] NuxtServerInit (0) | 2022.06.06 |
---|---|
[Vue+Nuxt.js] Vuex๋ฅผ ์ด์ฉํ์ฌ ์ฅ๋ฐ๊ตฌ๋ Page ๋ง๋ค๊ธฐ (0) | 2022.06.05 |
[Vue+Nuxt.js] Nuxt.js๋ฅผ ์ด์ฉํ์ฌ ์ผํ ์ํ ๋ชฉ๋ก ํ์ด์ง์ ์์ธ ํ์ด์ง ๊ฐ๋ฐ (0) | 2022.05.24 |
[Vue+Nuxt.js] Nuxt.js Data ํธ์ถ ๋ฐฉ์๊ณผ API ์ฐ๋ (0) | 2022.05.22 |
[Nuxt.js] ๋น๋๊ธฐ ๋ฐ์ดํฐ ํธ์ถ ๋ฐฉ๋ฒ (0) | 2022.05.22 |