본문 바로가기
Dev/Vue.js

[Vue.js] Today I Learned - 학습 노트 생성

by dev_jsk 2020. 10. 28.
728x90
반응형

학습 노트 생성

Today I Learned의 학습 노트를 추가할 수 있는 기능을 구현한다.

등록 페이지 라우터 연결

메인 페이지에서 등록 페이지 이동을 위한 라우터 연결을 구현한다.

// src/routes/index.js
import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

export default new VueRouter({
  mode: 'history',
  routes: [
    {
      path: '/',
      redirect: '/login',
    },
    // 등록 페이지 이동
    {
      path: '/add',
      component: () => import('@/views/PostAddPage.vue'),
    },
    {
      path: '*',
      component: () => import('@/views/NotFoundPage.vue'),
    },
  ],
});

등록 페이지 폼 데이터 바인딩 및 이벤트 연결

등록 페이지의 폼 데이터를 submit 버튼에 이벤트를 연결하여 바인딩 하도록 구현할 수 있다.

<!-- src/components/posts/PostAddForm.vue -->
<template>
  <div class="contents">
    <h1 class="page-header">Create Post</h1>
    <div class="form-wrapper">
      <!-- v-on:submit을 이용하여 submitForm 함수와 연결 -->
      <form class="form" @submit.prevent="submitForm">
        <div>
          <label for="title">Title: </label>
          <!-- v-model을 이용하여 데이터 바인딩 -->
          <input id="title" type="text" v-model="title" />
        </div>
        <div>
          <label for="contents">Contents: </label>
          <!-- v-model을 이용하여 데이터 바인딩 -->
          <textarea id="contents" type="text" rows="5" v-model="contents" />
        </div>
        <button class="btn" type="submit">Create</button>
      </form>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: '',
      contents: '',
    };
  },
  methods: {
    submitForm() {
      console.log('submit');
    },
  },
};
</script>

<style scoped>
.form-wrapper .form {
  width: 100%;
}
.btn {
  color: white;
}
</style>

등록 API 구현

등록 페이지에서 입력한 값을 바탕으로 등록 API를 호출하여 학습 노트를 생성할 수 있다. 추가적인 기능으로 등록 실패 에러에 대한 처리 및 본문 길이 유효성 검사도 구현한다.

<!-- src/api/index.js -->
<script>
import axios from 'axios';
import { setInterceptors } from './common/interceptors';


function createInstance() {
  const instance = axios.create({
    baseURL: process.env.VUE_APP_API_URL,
  });
  return setInterceptors(instance);
}
const instance = createInstance();

// 학습 노트 데이터를 생성하는 API
function createPost(postData) {
  return instance.post('posts', postData);
}

export { createPost };
</script>

<!-- src/components/posts/PostAddForm.vue -->
<template>
  <div class="contents">
    <h1 class="page-header">Create Post</h1>
    <div class="form-wrapper">
      <form class="form" @submit.prevent="submitForm">
        <div>
          <label for="title">Title: </label>
          <input id="title" type="text" v-model="title" />
        </div>
        <div>
          <label for="contents">Contents: </label>
          <textarea id="contents" type="text" rows="5" v-model="contents" />
          <!-- 본문 200자 유효성 검사 -->
          <p class="validation-text warning" v-if="!isContentsValid">
            Contents length must be less than 200
          </p>
        </div>
        <button class="btn" type="submit">Create</button>
      </form>
      <!-- 에러 메시지 표시 -->
      <p class="log">
        {{ logMessage }}
      </p>
    </div>
  </div>
</template>

<script>
import { createPost } from '@/api/index';

export default {
  data() {
    return {
      title: '',
      contents: '',
      logMessage: '',
    };
  },
  computed: {
    // 본문 200자 유효성 검사
    isContentsValid() {
      return this.contents.length <= 200;
    },
  },
  methods: {
    async submitForm() {
      // try-catch 문을 이용한 등록 에러 처리
      try {
        // 등록 API 함수 호출
        const response = await createPost({
          title: this.title,
          contents: this.contents,
        });
      } catch (error) {
        // 에러 메시지 표시
        this.logMessage = error.response.data.message;
      }
    },
  },
};
</script>
728x90
반응형

댓글