웹사이트 검색

Vue.js로 모달 구성 요소를 빌드하는 방법


소개

모달은 사용자가 읽거나 상호 작용해야 하는 콘텐츠에 사용자의 관심을 유도하는 사용자 경험 규칙입니다. 이들은 페이지의 나머지 콘텐츠를 가리거나 숨기는 일종의 배경과 함께 사용자의 시야에서 직접 콘텐츠의 작은 블록 형태를 취하는 경향이 있습니다. 사용자가 페이지로 돌아가려면 모달에 참여하거나 가능하면 닫아야 합니다.

이 기사에서는 Vue.js의 전환 및 슬롯을 사용하여 재사용 가능한 모달 구성 요소를 만드는 방법을 배웁니다.

전제 조건

이 자습서를 완료하려면 다음이 필요합니다.

  • Node.js를 로컬에 설치했습니다. Node.js를 설치하고 로컬 개발 환경을 만드는 방법에 따라 수행할 수 있습니다.

1단계 - 프로젝트 설정

@vue/cli를 사용하여 새 Vue.js 프로젝트를 만들 수 있습니다.

터미널 창에서 다음 명령을 사용합니다.

  1. npx @vue/cli create --default vue-modal-component-example

이것은 Vue.js 프로젝트 생성을 위한 기본 구성을 사용합니다.

새로 생성된 프로젝트 디렉토리로 이동합니다.

  1. cd vue-modal-component-example

오류가 없는지 확인하려면 프로젝트를 시작하십시오.

  1. npm run serve

웹 브라우저에서 로컬 앱(일반적으로 localhost:8080)을 방문하면 \Welcome to Your Vue.js App\ 메시지가 표시됩니다.

이 스캐폴딩 세트를 사용하여 모달 구성 요소에 대한 작업을 시작할 수 있습니다.

2단계 - 모달 구성 요소 만들기

먼저 프로젝트 디렉토리 내에서 src/components 아래에 새 Modal.vue 파일을 만듭니다.

템플릿을 정의하여 시작하겠습니다. 배경 음영에 대한 div, 모달 상자 역할을 위한 div 및 해당 구조를 정의하는 일부 요소가 필요합니다.

<template>
  <div class="modal-backdrop">
    <div class="modal">
      <slot name="header">
      </slot>

      <slot name="body">
      </slot>

      <slot name="footer">
      </slot>
    </div>
  </div>
</template>

props를 사용하여 머리글, 본문 및 바닥글을 제공할 수 있지만 슬롯을 사용하면 더 많은 유연성이 허용됩니다.

슬롯을 사용하면 다른 유형의 본문 콘텐츠와 함께 동일한 모달을 재사용할 수 있습니다.

모달을 사용하여 메시지를 표시할 수 있지만 양식과 함께 동일한 모달을 재사용하여 요청을 제출할 수 있습니다.

일반적으로 props는 구성 요소를 구축하기에 충분하지만 prop을 통해 HTML을 제공하려면 v-html을 사용하여 렌더링해야 합니다. 이는 XSS 공격으로 이어질 수 있습니다.

여기에서는 이름이 지정된 슬롯을 사용하여 동일한 구성 요소에서 둘 이상의 슬롯을 사용할 수 있습니다.

명명된 슬롯을 정의하면 해당 이름으로 식별하는 모든 항목이 원래 슬롯 대신 렌더링됩니다. 자리 표시자로 생각하십시오. 자리 표시자와 마찬가지로 슬롯에는 아무 것도 제공되지 않을 때 렌더링되는 기본 콘텐츠가 있을 수 있습니다.

제공된 콘텐츠가 <slot> 태그를 대체하기 때문에 섹션에 원하는 클래스가 있는지 확인하려면 각 슬롯을 래핑해야 합니다.

기본 모달처럼 보이도록 슬롯, 래퍼 요소 및 초기 CSS에 대한 몇 가지 기본값을 설정해 보겠습니다.

템플릿 위에 구성 요소 이름과 모달을 닫는 방법을 추가합니다.

<script>
  export default {
    name: 'Modal',
    methods: {
      close() {
        this.$emit('close');
      },
    },
  };
</script>

그런 다음 템플릿을 수정하여 슬롯을 래핑하고 기본값을 제공하고 모달을 닫기 위한 버튼도 표시합니다.

<template>
  <div class="modal-backdrop">
    <div class="modal">
      <header class="modal-header">
        <slot name="header">
          This is the default title!
        </slot>
        <button
          type="button"
          class="btn-close"
          @click="close"
        >
          x
        </button>
      </header>

      <section class="modal-body">
        <slot name="body">
          This is the default body!
        </slot>
       </section>

      <footer class="modal-footer">
        <slot name="footer">
          This is the default footer!
        </slot>
        <button
          type="button"
          class="btn-green"
          @click="close"
        >
          Close Modal
        </button>
      </footer>
    </div>
  </div>
</template>

그런 다음 템플릿 아래에 구성 요소에 대한 스타일을 추가합니다.

<style>
  .modal-backdrop {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(0, 0, 0, 0.3);
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .modal {
    background: #FFFFFF;
    box-shadow: 2px 2px 20px 1px;
    overflow-x: auto;
    display: flex;
    flex-direction: column;
  }

  .modal-header,
  .modal-footer {
    padding: 15px;
    display: flex;
  }

  .modal-header {
    position: relative;
    border-bottom: 1px solid #eeeeee;
    color: #4AAE9B;
    justify-content: space-between;
  }

  .modal-footer {
    border-top: 1px solid #eeeeee;
    flex-direction: column;
    justify-content: flex-end;
  }

  .modal-body {
    position: relative;
    padding: 20px 10px;
  }

  .btn-close {
    position: absolute;
    top: 0;
    right: 0;
    border: none;
    font-size: 20px;
    padding: 10px;
    cursor: pointer;
    font-weight: bold;
    color: #4AAE9B;
    background: transparent;
  }

  .btn-green {
    color: white;
    background: #4AAE9B;
    border: 1px solid #4AAE9B;
    border-radius: 2px;
  }
</style>

이 모든 조각들이 모이면 모달 구성 요소가 완성됩니다. App.vue에서 이 새로운 구성 요소를 가져오고 작동을 관찰할 수 있습니다.

App.vue를 수정하여 템플릿을 변경하고 showModal, closeModalisModalVisible을 추가합니다.

<template>
  <div id="app">
    <button
      type="button"
      class="btn"
      @click="showModal"
    >
      Open Modal!
    </button>

    <Modal
      v-show="isModalVisible"
      @close="closeModal"
    />
  </div>
</template>

<script>
  import modal from './components/Modal.vue';

  export default {
    name: 'App',
    components: {
      Modal,
    },
    data() {
      return {
        isModalVisible: false,
      };
    },
    methods: {
      showModal() {
        this.isModalVisible = true;
      },
      closeModal() {
        this.isModalVisible = false;
      }
    }
  };
</script>

이 코드는 Modal 구성 요소를 가져오고 상호 작용할 Modal 열기 버튼을 표시합니다.

참고: App.js 파일에서 선택적으로 슬롯을 참조하고 기본 콘텐츠를 바꿀 수 있습니다.

<Modal
  v-show="isModalVisible"
  @close="closeModal"
>
  <template v-slot:header>
    This is a new modal header.
  </template>

  <template v-slot:body>
    This is a new modal body.
  </template>

  <template v-slot:footer>
    This is a new modal footer.
  </template>
</Modal>

웹 브라우저에서 애플리케이션을 보고 모달을 열고 닫아 예상대로 작동하는지 확인합니다.

3단계 - 전환 추가

전환을 사용하여 더 매끄럽게 열리고 닫히는 것처럼 보이게 할 수 있습니다.

Vue는 들어오고 나가는 전환을 추가할 수 있는 transition이라는 래퍼 구성 요소를 제공합니다. 이 래퍼 구성 요소는 모든 요소 또는 구성 요소에 사용할 수 있으며 CSSJavaScript 후크를 모두 허용합니다.

전환에 의해 래핑된 구성 요소 또는 요소가 삽입되거나 제거될 때마다 Vue는 주어진 요소에 CSS 전환이 있는지 확인하고 적시에 추가하거나 제거합니다. JavaScript 후크도 마찬가지지만 이 경우에는 CSS만 사용합니다.

요소가 추가되거나 제거되면 들어가기 및 나가기 전환에 대해 6개의 클래스가 적용됩니다. 각각에는 전환 이름이 접두사로 붙습니다.

먼저 전환 래퍼 구성 요소를 모달에 추가하여 시작하겠습니다.

<template>
  <transition name="modal-fade">
    <div class="modal-backdrop">
      <div class="modal">
        ...
      </div>
    </div>
  </transition>
</template>

이제 적용된 클래스를 사용하여 불투명도가 천천히 사라지도록 전환을 추가해 보겠습니다.

<style>
  ...

  .modal-fade-enter,
  .modal-fade-leave-to {
    opacity: 0;
  }

  .modal-fade-enter-active,
  .modal-fade-leave-active {
    transition: opacity .5s ease;
  }
</style>

처음에 모달은 opacity 속성 값이 0인 숨겨진 상태로 나타납니다.

모달이 열리면 .modal-fade-enter-active 클래스가 적용되고 opacity 속성에 대한 CSS 전환이 에 적용됩니다.5< ease 애니메이션 타이밍 기능을 사용하여초.

모달을 나가면 그 반대가 됩니다. modal-fade-leave-active 클래스가 적용되고 모달이 페이드 아웃됩니다.

웹 브라우저에서 애플리케이션을 보고 모달이 페이드 인 및 페이드 아웃되는지 확인합니다.

4단계 - 접근성 추가

ARIA 속성으로 모달 구성 요소에 액세스할 수 있도록 만들고 싶을 것입니다.

role=\dialog\를 추가하면 보조 소프트웨어가 구성 요소를 나머지 사용자 인터페이스와 분리된 응용 프로그램 대화 상자로 식별하는 데 도움이 됩니다.

또한 aria-labelledbyaria-describedby 속성으로 적절하게 레이블을 지정해야 합니다.

닫기 버튼에 aria-label 속성을 추가합니다.

<template>
  <transition name="modal-fade">
    <div class="modal-backdrop">
      <div class="modal"
        role="dialog"
        aria-labelledby="modalTitle"
        aria-describedby="modalDescription"
      >
        <header
          class="modal-header"
          id="modalTitle"
        >
          <slot name="header">
            This is the default title!
          </slot>
          <button
            type="button"
            class="btn-close"
            @click="close"
            aria-label="Close modal"
          >
            x
          </button>
        </header>

        <section
          class="modal-body"
          id="modalDescription"
        >
          <slot name="body">
            This is the default body!
          </slot>
        </section>

        <footer class="modal-footer">
          <slot name="footer">
            This is the default footer!
          </slot>
          <button
            type="button"
            class="btn-green"
            @click="close"
            aria-label="Close modal"
          >
            Close Modal
          </button>
        </footer>
      </div>
    </div>
  </transition>
</template>

모달 구성 요소의 최종 버전은 이제 다음과 유사합니다.

<script>
  export default {
    name: 'Modal',
    methods: {
      close() {
        this.$emit('close');
      },
    },
  };
</script>

<template>
  <transition name="modal-fade">
    <div class="modal-backdrop">
      <div class="modal"
        role="dialog"
        aria-labelledby="modalTitle"
        aria-describedby="modalDescription"
      >
        <header
          class="modal-header"
          id="modalTitle"
        >
          <slot name="header">
            This is the default tile!
          </slot>
          <button
            type="button"
            class="btn-close"
            @click="close"
            aria-label="Close modal"
          >
            x
          </button>
        </header>

        <section
          class="modal-body"
          id="modalDescription"
        >
          <slot name="body">
            This is the default body!
          </slot>
        </section>

        <footer class="modal-footer">
          <slot name="footer">
            This is the default footer!
          </slot>
          <button
            type="button"
            class="btn-green"
            @click="close"
            aria-label="Close modal"
          >
            Close me!
          </button>
        </footer>
      </div>
    </div>
  </transition>
</template>

<style>
  .modal-backdrop {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background-color: rgba(0, 0, 0, 0.3);
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .modal {
    background: #FFFFFF;
    box-shadow: 2px 2px 20px 1px;
    overflow-x: auto;
    display: flex;
    flex-direction: column;
  }

  .modal-header,
  .modal-footer {
    padding: 15px;
    display: flex;
  }

  .modal-header {
    position: relative;
    border-bottom: 1px solid #eeeeee;
    color: #4AAE9B;
    justify-content: space-between;
  }

  .modal-footer {
    border-top: 1px solid #eeeeee;
    flex-direction: column;
  }

  .modal-body {
    position: relative;
    padding: 20px 10px;
  }

  .btn-close {
    position: absolute;
    top: 0;
    right: 0;
    border: none;
    font-size: 20px;
    padding: 10px;
    cursor: pointer;
    font-weight: bold;
    color: #4AAE9B;
    background: transparent;
  }

  .btn-green {
    color: white;
    background: #4AAE9B;
    border: 1px solid #4AAE9B;
    border-radius: 2px;
  }

  .modal-fade-enter,
  .modal-fade-leave-to {
    opacity: 0;
  }

  .modal-fade-enter-active,
  .modal-fade-leave-active {
    transition: opacity .5s ease;
  }
</style>

이것은 접근성 및 전환이 있는 모달 구성 요소의 기초입니다.

결론

이 기사에서는 Vue.js로 모달 컴포넌트를 빌드했습니다.

구성요소를 재사용할 수 있도록 슬롯, 더 나은 사용자 경험을 제공하기 위해 전환, 구성요소에 더 쉽게 액세스할 수 있도록 ARIA 속성을 실험했습니다. .

Vue.js에 대해 자세히 알아보려면 연습 및 프로그래밍 프로젝트에 대한 Vue.js 주제 페이지를 확인하세요.