본문 바로가기
Programming/Vue

[실습] 뷰(Vue)로 공지사항/게시판 구현하기 - 상세 화면 기능 개발

by 돌방로그 2023. 2. 3.


오늘의 Vue.js 실습 목표는 "공지사항/게시판 만들어보기!" 입니다.

본 게시글에서 다루는 사항은 공지사항/게시판 상세 화면의 기능을 구현하는 과정입니다.

Spring Boot로 구현한 REST API를 통해 DB 데이터를 조작하는 과정은 별도의 포스팅에서 다룰 예정입니다.

 


공지사항/게시판 구현하기 - 상세 화면

사전 준비

아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.

 


결과 이미지

구현하기에 앞서 본 글을 따라하시면 아래와 같이 공지사항 상세 화면의 레이아웃이 구성되는 것을 확인하실 수 있습니다.

▶ 초기 화면, OK 버튼 클릭한 경우

▶ Register 버튼 클릭한 경우

▶ View Detail 버튼 클릭한 경우

▶ Modify 버튼 클릭한 경우

 


소스 코드

src\components\user-web\notice\NoticeDetail.vue

전체 코드를 확인하실 분들은 아래 더보기를 클릭해주세요.

더보기
<template>
  <div class="ma-md-5">
    <div class="d-flex justify-end">
      <v-btn
        text
        outlined
        class="mx-md-1 elevation-2"
        :class="{ visibility: getVisibleStatusBtns() }"
        :disabled="getEnableStatusElements()"
        @click="refreshElements"
        >REFRESH
      </v-btn>
    </div>

    <div class="mt-5">
      <v-combobox
        outlined
        dense
        hide-selected
        required
        label="Category"
        :items="categories"
        v-model="category"
        :disabled="getEnableStatusElements()"
      ></v-combobox>
      <v-text-field
        required
        label="Title"
        v-model="title"
        :disabled="getEnableStatusElements()"
      ></v-text-field>
      <v-textarea
        required
        label="Content"
        v-model="content"
        :disabled="getEnableStatusElements()"
      ></v-textarea>
    </div>

    <div class="d-flex justify-end">
      <v-btn
        text
        outlined
        class="mx-md-1 elevation-2"
        :class="{ visibility: getVisibleStatusBtns() }"
        :disabled="getEnableStatusElements()"
        @click="clickCancelBtn"
        >CANCEL
      </v-btn>
      <v-btn
        text
        outlined
        class="mx-md-1 elevation-2"
        :class="{ visibility: getVisibleStatusBtns() }"
        :disabled="getEnableStatusElements()"
        @click="clickOkBtn"
        >OK
      </v-btn>
    </div>
  </div>
</template>

<script>
const MODE_INIT = "INIT";
const MODE_VIEW = "VIEW";
const MODE_DELETE = "DELETE";

export default {
  props: ["mode", "notice"],
  data() {
    return {
      id: -1,
      category: [],
      title: "",
      content: "",

      categories: ["Competition", "System Check", "Etc"],
    };
  },
  updated: function () {
    this.$nextTick(function () {
      if (this.id != this.notice.id) {
        this.id = this.notice.id;
        this.refreshElements();
      }
    });
  },
  methods: {
    getEnableStatusElements: function () {
      return (
        this.mode == MODE_INIT ||
        this.mode == MODE_DELETE ||
        this.mode == MODE_VIEW
      );
    },
    getVisibleStatusBtns: function () {
      return this.mode == MODE_VIEW;
    },
    initializeElements: function () {
      this.category = [];
      this.title = "";
      this.content = "";
    },
    refreshElements: function () {
      this.category = this.notice.category;
      this.title = this.notice.title;
      this.content = this.notice.content;
    },
    clickOkBtn: function () {
      this.initializeElements();

      this.$emit("finishProcess");
    },
    clickCancelBtn: function () {
      this.initializeElements();
    },
  },
};
</script>

<style scoped>
.visibility {
  visibility: hidden;
}
</style>

 

<template>

<template>
  <div class="ma-md-5">
    <div class="d-flex justify-end">
      <v-btn
        ...
        :class="{ visibility: getVisibleStatusBtns() }"
        :disabled="getEnableStatusElements()"
        @click="refreshElements"
        >REFRESH
      </v-btn>
    </div>

    <div class="mt-5">
      <v-combobox
        ...
        v-model="category"
        :disabled="getEnableStatusElements()"
      ></v-combobox>
      <v-text-field
        ...
        v-model="title"
        :disabled="getEnableStatusElements()"
      ></v-text-field>
      <v-textarea
        ...
        v-model="content"
        :disabled="getEnableStatusElements()"
      ></v-textarea>
    </div>

    <div class="d-flex justify-end">
      <v-btn
        ...
        :class="{ visibility: getVisibleStatusBtns() }"
        :disabled="getEnableStatusElements()"
        @click="clickCancelBtn"
        >CANCEL
      </v-btn>
      <v-btn
        ...
        :class="{ visibility: getVisibleStatusBtns() }"
        :disabled="getEnableStatusElements()"
        @click="clickOkBtn"
        >OK
      </v-btn>
    </div>
  </div>
</template>
  • UI
    • :class = Visibility 부합되는 요소에 대해서만 보여지도록 설정하도록 코드 정의
    • :disabled = 버튼 요소의 Enable 상태를 상위 컴포넌트에서 전달받은 모드를 감지하여 변화되도록 함수 호출 코드 정의
  • Event
    • @click = 버튼 요소에 이벤트 발생시 호출할 함수를 연결하는 코드 정의
    • v-model = 버튼 외 요소에 변경된 값을 감지하는 코드 정의

 

<script>

<script>
const MODE_INIT = "INIT";
const MODE_VIEW = "VIEW";
const MODE_DELETE = "DELETE";

export default {
  props: ["mode", "notice"],
  data() {
    return {
      id: -1,
      category: [],
      title: "",
      content: "",

      categories: [...],
    };
  },
  updated: function () {
    this.$nextTick(function () {
      if (this.id != this.notice.id) {
        this.id = this.notice.id;
        this.refreshElements();
      }
    });
  },
  methods: {
    getEnableStatusElements: function () {
      return (
        this.mode == MODE_INIT ||
        this.mode == MODE_DELETE ||
        this.mode == MODE_VIEW
      );
    },
    getVisibleStatusBtns: function () {
      return this.mode == MODE_VIEW;
    },
    initializeElements: function () {
      this.category = [];
      this.title = "";
      this.content = "";
    },
    refreshElements: function () {
      this.category = this.notice.category;
      this.title = this.notice.title;
      this.content = this.notice.content;
    },
    clickOkBtn: function () {
      this.initializeElements();

      this.$emit("finishProcess");
    },
    clickCancelBtn: function () {
      this.initializeElements();
    },
  },
};
</script>
  • props 영역
    • 상위 컴포넌트에서 전달받은 데이터
      • mode: 조작 모드(등록, 수정, 삭제, 상세보기) 정보
      • notice: 선택된 공지사항/게시글 정보
  • data 영역
    • id: 상위 컴포넌트에서 전달받은 정보의 키(Key) 정보가 설정되는 변수
    • category: Category 필드에서 입력된 데이터가 담긴 변수
    • title: Title 필드에서 입력된 데이터가 담긴 변수
    • content: Content 필드에서 입력된 데이터가 담긴 변수
  • updated 영역
    • 동일한 id를 지닌 notice에 대한 정보가 아닌 경우, 필드에 대한 값 변경 처리
  • methods 영역
    • getEnableStatusElements: 요소의 활성화 조건 부합 여부를 확인하는 함수
    • getVisibleStatusBtns: 버튼의 Visibility 조건 부합 여부를 확인하는 함수
    • initializeElements: 필드에 모든 값을 초기화하는 함수
    • refreshElements: 필드에 모든 값을 모드 변경할 때 전달받은 값으로 설정하는 함수
    • clickOkBtn: '등록', '수정'에 관련한 DB 조작이 처리를 요청하는 함수
    • clickCancelBtn: 값 입력 이전 상태로 돌아가는 함수

 

<style>

<style scoped>
.visibility {
  visibility: hidden;
}
</style>
  • 특정 조건일 때 화면에 표시되지 않으나 공간은 차지하고 있도록 설정하는 CSS 효과

 


References

댓글