결과 화면

 

1. BaseModal 컴포넌트 만들기

  • components/base/BaseModal.vue

<BaseModal> 컴포넌트는 여러 가지 모양의 모달에서 사용될 기본 틀이다.

  1. 모달의 경우, 주로 닫기 버튼과 제목, 내용 영역으로 구성되기 때문에 닫기 버튼과 <slot>으로 기본 레이아웃을 만든다.
  2. 모달 바깥쪽 영역과 닫기 버튼을 누르면 모달이 닫히는 이벤트가 필요하기 때문에 $emit 을 이용해 클릭 이벤트를 만든다.
  3. 공통으로 적용할 css/scss를 작성한다.
<template>
  <div
    class="base-modal"
    @click.self="$emit('close')">
    <div class="wrap">
      <BaseButton @click="$emit('close')">X</BaseButton>

      <div class="title">
        <slot name="title"/>
      </div>

      <div class="content">
        <slot name="content"/>
      </div>
    </div>
  </div>
</template>

<script>
import BaseButton from '@/components/base/BaseButton'

export default {
  name: 'BaseModal',

  components: {
    BaseButton
  }
}
</script>

<style lang="scss" scoped>
.base-modal {
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1000;
  background-color: rgba(0, 0, 0, 0.5);

  .wrap {
    position: relative;
    width: 90%;
    max-width: 500px;
    min-height: 300px;
    background-color: #fff;
    border-radius: 16px;

    .base-button {
      position: absolute;
      top: 20px;
      right: 20px;
      font-size: 20px;
      font-weight: 700;
    }

    .title {
      margin: 20px auto;

      h3 {
        font-size: 26px;
        font-weight: 700;
        text-align: center;
      }
    }

    .content {
      p {
        font-size: 16px;
      }
    }
  }
}
</style>

 

2. 필요한 modal 컴포넌트 만들기

  • components/modal/ModalCookie.vue

<slot>을 사용해 모달 안의 내용을 작성한다.

해당 방식으로 여러 가지 모달을 만들 수 있다.

<template>
  <BaseModal @close="$emit('close')">
    <h3 slot="title">Cookie Modal</h3>
    <p slot="content">쿠키 모달입니다.</p>
  </BaseModal>
</template>

<script>
import BaseModal from '@/components/base/BaseModal'

export default {
  name: 'ModalCookie',

  components: {
    BaseModal
  }
}
</script>

 

3. 페이지에 modal import 하기

  • pages/index.vue
  1. 만든 <ModalCookie> 컴포넌트를 import 시킨다.
  2. isModalCookie 속성을 만들어 v-if가 true 이면 모달이 나타나고, false 이면 모달이 사라지게 만든다. 
  3. ModalCookieToggle 클릭 이벤트를 만든다.
<template>
  <TheLayout>
    <BaseButton @click="ModalCookieToggle">쿠키 모달 열기</BaseButton>

    <ModalCookie
      v-if="isModalCookie"
      @close="ModalCookieToggle"/>
  </TheLayout>
</template>

<script>
import TheLayout from '@/components/layout/TheLayout'
import BaseButton from '@/components/base/BaseButton'
import ModalCookie from '@/components/modal/ModalCookie'

export default {
  name: 'Main',

  components: {
    TheLayout,
    BaseButton,
    ModalCookie
  },

  data() {
    return {
      isModalCookie: false
    }
  },

  methods: {
    ModalCookieToggle() {
      this.isModalCookie = !this.isModalCookie
    }
  }
}
</script>

결과 화면

 

1. RouterName 변수 만들기

  • configs/router.js
  1. RouterName 변수(객체)를 만든다.
  2. 라우터 변수의 이름과 경로를 정의한다. (경로는 pages 폴더에 만든 .vue 파일의 경로와 동일하게 만든다.)

RouterName 변수 파일을 따로 만드는 이유는 피씨 메뉴, 모바일 메뉴, 사이트맵 등 여러 곳에서 사용했을 경우, 이름 또는 경로가 변경되면 여러 번 수정해야 하기 때문에 router 파일을 하나 만들어 import 시켜서 사용하면 한 번만 수정하면 된다.

export const RouterName = {
  MAIN: '/',
  SUB: '/sub',

  AUTH_LOGIN: '/auth/login'
}

 

2. TheHeader 컴포넌트 만들기

  • components/layout/TheHeader.vue
  1. <script> 태그에 { RouterName }을  import 시킨다.
  2. <script> 태그의 data() 영역에 navigation 변수(배열)를 만든다.
  3. name은 네비게이션 이름, to는 RouterName에 작성한 라우터 변수를 작성한다.
  4. <nav> 태그에 v-for를 사용해 네비게이션을 만든다.
<template>
  <header class="wrap">
    <nav>
      <NuxtLink
        v-for="(nav, key) in navigation"
        :key="`nav-${key}`"
        :to="{ path: `${nav.to}`}">
        {{ nav.name }}
      </NuxtLink>
    </nav>
  </header>
</template>

<script>
import { RouterName } from '@/configs/router'

export default {
  name: 'TheHeader',

  data() {
    return {
      navigation: [
        {
          name: '메인',
          to: RouterName.MAIN
        },
        {
          name: '서브',
          to: RouterName.SUB
        },
        {
          name: '로그인',
          to: RouterName.AUTH_LOGIN
        }
      ]
    }
  }
}

<style lang="scss" scoped>
header {
  ...
}
</style>

 

3. TheHeader 컴포넌트 import 시키기

  • components/layout/TheLayout.vue
<template>
  <div>
    <TheHeader/>

    <main class="wrap">
      <slot/>
    </main>

    <footer></footer>
  </div>
</template>

<script>
import TheHeader from '@/components/layout/TheHeader'

export default {
  name: 'TheLayout',

  components: {
    TheHeader
  }
}
</script>

 

  • pages/index.vue
<template>
  <TheLayout>
    <h1>메인 페이지</h1>
  </TheLayout>
</template>

<script>
import TheLayout from '@/components/layout/TheLayout'

export default {
  name: 'Main',

  components: {
    TheLayout
  }
}
</script>

v-if

v-if 디렉티비는 조건부로 블록을 렌더링 하고, 블록은 디렉티브 표현식이 ture 일 때만 렌더링 된다.

 

v-else

v-if에 대한 else 블록을 렌더링 하고, 블록은 디렉티브 표현식이 false 일 때만 렌더링 된다.

 

결과 화면

 

  • pages/index.vue

실제 프로젝트를 진행할 때에는 데이터(게시판, 공지사항 등)는 API로 받게 된다. 

데이터가 아무것도 없을 때에도 레이아웃을 보여주어야 하기 때문에 v-if와 v-else를 사용해 렌더링을 한다.

 

v-if 조건문에 맞춰 dataList 배열의 길이가 0이면 <h2> 태그를 렌더링 하고,

dataList 배열의 길이가 0이 아니라면 <ul> 태그를 렌더링 한다.

<template>
  <TheLayout>
    <h2 v-if="dataList.length === 0">데이터가 없습니다.</h2>

    <ul v-else>
      <li
        v-for="(list, key) in dataList"
        :key="`list-${key}`">
        <h2>{{ list.title }}</h2>
        <p>{{ list.content }}</p>
        <span>{{ list.date }}</span>
      </li>
    </ul>
  </TheLayout>
</template>

<script>
import TheLayout from "@/components/layout/TheLayout"

export default {
  name: 'Main',

  components: {
    TheLayout
  },

  data() {
    return {
      dataList: []
    }
  }
}
</script>

v-for

게시판의 게시글 리스트나 반복적인 내용을 보여줘야 할 때 v-for 디렉티브를 사용한다.

v-for="item in items":key 형태이다.

뷰에서 사용하는 for문이라고 생각하면 된다.

 

결과 화면

 

v-for 사용하기

  • pages/index.vue
  1. <script> 태그 안 data() 영역에 배열을 만든다. (dataList)
  2. <li> 태그가 반복되어야 하기 때문에 <li> 태그에 v-for와 :key를 작성한다.
  3. 중괄호 {{ ~ }} 안에 배열의 속성값을 작성한다.
<template>
  <TheLayout>
    <ul>
      <li
        v-for="(list, key) in dataList"
        :key="`list-${key}`">
        <h2>{{ list.title }}</h2>
        <p>{{ list.content }}</p>
        <span>{{ list.date }}</span>
      </li>
    </ul>
  </TheLayout>
</template>

<script>
import TheLayout from "@/components/layout/TheLayout"

export default {
  name: 'Main',

  components: {
    TheLayout
  },

  data() {
    return {
      dataList: [
        {
          title: 'Nuxt.js',
          content: 'Nuxt.js란, Vue.js 애플리케이션을 구축할 수 있는 오픈 소스 프레임워크이다.',
          date: '2023-10-01'
        },
        {
          title: 'Slot',
          content: '컴포넌트를 랜더링 할 때 html로 작성한 코드가 컴포넌트의 slot 부분으로 교체된다.',
          date: '2023-10-02'
        },
        {
          title: '뷰 SASS/SCSS 적용하기',
          content: 'sass/scss를 적용하고 싶은 .vue 파일에서 script 태그 아래에 style 태그를 작성한다.',
          date: '2023-10-03'
        }
      ]
    }
  }
}
</script>

Nuxt.js란

Nuxt.js란, Vue.js 애플리케이션을 구축할 수 있는 오픈 소스 프레임워크이다.

Nuxt.js 공식 문서: https://nuxt.com/

  • 코드 분할
  • SSR, SPA 등 렌더링 결정 가능
  • 서버 측 렌더링
  • 최적화된 이미지
  • SEO

 


1. npm init nuxt-app

터미널에서 아래 명령어를 실행하고, 나오는 옵션들을 선택한다.

프로젝트 이름, Javascript/Typescript 언어 선택 등을 설정할 수 있다.

잘 모르겠으면 전부 앤터를 누른다.

npm init nuxt-app 프로젝트 이름

 

 

2. 로컬호스트 연결 확인하기

설치한 프로젝트로 이동 또는 프로젝트를 열고, 터미널에서 아래 명령어를 실행한다.

yarn dev

또는

yarn build
yarn start

 

 

3. 결과 화면

로컬 호스트 접속 후, 아래 화면이 나온다면 로컬호스트 연결에 성공한 것이다.

 

 

4. 폴더 구조

+ Recent posts