[Vue] Vuetify 사용하기 - 기본설정, 컴포넌트재사용, v-model, (Snackbar, Modal 재사용 컴포넌트로 분리하기)

권준혁·2020년 12월 13일
0

vue

목록 보기
8/8
post-thumbnail

Vue의 가장 많이 사용하는 디자인 템플릿 vuetify에 대한 포스팅이다.

기본설정

vue cli 버전이 3.0 이상인지 확인한다.

vue --version

vue add로 플러그인을 추가한다.

vue add vuetify

추가한 뒤에는 template내에서 <v-card> 처럼 v로 시작하는 prefix를 붙여서 바로 사용할 수 있게된다.

vue-cli명령어 vue add로 추가해서 사용하는 경우 vue.config.js, plugin폴더, main.js가 자동으로 수정 되는 점을 인지하고있어야 한다.
다른 플러그인 추가와 마찬가지로 저장소에 저장한 뒤 하는 것이 권장사항이다.


사용해보기 - 재사용과 v-model

재사용하기위해 컴포넌트를 분리하는 것은 어렵지 않다. 그저 파일을 분리해 모듈화하고 모듈시스템을 이용해 사용하면 된다.

하지만, props를 전달받아 자식컴포넌트에서 직접 수정하려고 한다면 에러가 발생한다.
vuetify에서 model, alert처럼 컴포넌트 내에서 애니메이션 효과를 상태값으로 가지고 있는 경우, 부모 컴포넌트에서 전달한 props를 바로 v-model에 사용할 수 없다.

v-model로 props를 직접 연결한 경우, vue/no-mutating-props 에러가 발생한다.
이런 경우 computed속성으로 get, set 메서드까지 구현해주면 된다.

재사용 가능한 Modal컴포넌트 만들어보기

재사용가능한 Modal기능 컴포넌트를 만들어보려고 한다.
slot을 이용해 내부 컨텐츠를 부모 컴포넌트에서 커스터마이징 할 수 있다.

속성값으로 전달받는 데이터

  • open : Modal 컴포넌트를 보여줄 것인지 나타내는 상태
  • padding: 컨텐츠 패딩
  • closeModal: Modal창 닫는 함수

모달 컴포넌트

<template>
  <v-dialog v-model="openModal" max-width="570px" class="dialog" :scrollable="true">
    <div class="modal-container" :style="{ padding }">
      <slot name="content"></slot>
    </div>
  </v-dialog>
</template>

<script>
export default {
  name: "Modal",
  data() {
    return {};
  },
  props: ["open", "padding"],
  methods: {},
  computed: {
    openModal: {
      get() {
        return this.open;
      },
      set(newValue) {
        console.log(newValue);
        this.$emit("closeModal");
      },
    },
  },
};
</script>

computed속성에 openModal이라는 데이터를 작성하고 get,set을 구현했다.
set메서드는 newValue를 인자로 받는다.
this.$emit("closeModal") 로 부모에서 전달한 함수를 실행했다.
필요하다면 this.$emit("closeModal", newValue)로 newValue를 전달해도 된다.

부모컴포넌트

      <modal :open="agreement.agreementOpenFirst" padding="20px" @closeModal="onClickCloseModal">
        <div slot="content">
          <div id="modal-slot-title-signin">개인정보 이용약관 동의</div>
          <div id="modal-slot-content-signin">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Et ut laborum dolores asperiores enim dignissimos eius ducimus vel nisi,
            sint, velit eos voluptate deserunt tenetur excepturi nobis
            doloribus veniam quia. Lorem ipsum dolor sit amet consectetur adipisicing elit. Et ut laborum dolores asperiores enim dignissimos
            eius ducimus vel nisi, sint, velit eos voluptate deserunt
            tenetur excepturi nobis doloribus veniam quia. Lorem ipsum dolor sit amet consectetur adipisicing elit. 
            Et ut laborum dolores asperiores enim dignissimos eius ducimus vel nisi, sint, velit
          </div>
          <div id="modal-slot-footer-signin">
            <v-btn class="btn prev-btn" @click="onClickAgree1"> 동의하기 </v-btn>
            <v-btn class="btn next-btn" @click="onClickCloseModal"> 닫 기 </v-btn>
          </div>
        </div>
      </modal>

slot으로 컨텐츠를 전달하고있다.
일반적인 사이트에서 회원가입 중 자주 볼 수 있는 "약관 보기" 기능을 모달로 구현한 것이다.
하단에는 동의하기, 닫기 버튼이 있다.
부모컴포넌트의 데이터 agreement.agreementOpenFirst가 open속성으로 들어가고, padding값은 20px로 설정했다. closeModal이벤트 함수 도 전달해준다.

v-model은 양방향으로 데이터 바인딩이 되기 때문에
컴포넌트에서도 자유롭게 데이터를 변경할 수 있는 값을 넣어줘야 한다.


재사용 가능한 Alert컴포넌트 만들어보기


Alert 컴포넌트

<template lang="html">
  <v-alert v-model="openAlert" class="toast" transition="fade" :type="type">
    {{ description }}
  </v-alert>
</template>

<script>
export default {
  name: "action",
  props: ["open", "isSuccess", "description"],
  data() {
    return {};
  },
  watch: {
    open(newVal) {
      if (newVal) {
        setTimeout(() => {
          this.$emit("closeAlert");
        }, 4000);
      }
    },
  },
  computed: {
    type() {
      return this.isSuccess ? "success" : "error";
    },
    openAlert: {
      get() {
        return this.open;
      },
      set() {
        this.$emit("closeAlert");
      },
    },
  },
};
</script>

React Material-ui에서 Snackbar라고 불리는 컴포넌트다. vuetify에서는 alert라고 하는 것 같다.
회원가입 폼에서 유효성 검사에서 사용했다.

부모컴포넌트에서 주는 open속성값을 watch한다. open이 true로 바뀌었을 경우 4초뒤 closeAlert를 실행시킨다.
아까 Modal과 마찬가지로 closeAlert를 set내부에서 구현해줘야 닫기 버튼이 있는 Alert에서도 잘 동작한다.


profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글