ساخت کامپوننت modal برای vuejs

17 تیر 1397
modal success

کامپوننت modal در واقع همان کامپوننتی است که به هنگام کلیک روی یک دکمه یا لینک، بدون رفرش شدن صفحه، اطلاعات موردنظر ما درون یک جعبه به صورت پاپ آپ نمایش داده می شود. هر پروژه معمولا باید یک modal component داشته باشد .اما ایجاد یک کامپوننت قابل دسترس که در تجهیزات هوشمند مختلف کار کند، قطعا هیجان انگیز خواهد بود. در این مقاله یاد می گیرید که چگونه با استفاده از transition و slot ها یک کامپوننت modal با قابلیت استفاده مجدد ایجاد کنید.

تعریف ساختار Template یا قالب

کارمان را با تعریف template شروع می کنیم. ابتدا به یک div برای backdrop shade نیاز داریم، همچنین یک div که به عنوان modal box عمل می کند و علاوه بر این چند المان دیگر برای تعریف ساختار modal احتیاج داریم. بنابراین template به صورت زیر تعریف می شود:

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

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

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

آیا به نحوه استفاده از slot توجه کردید؟ ما در اینجا از slot برای تعریف header، body، footer استفاده کردیم، اما slot ها انعطاف پذیری بیشتری را در اختیار ما می گذارند.

Slot ها امکان استفاده مجدد از modal های یکسان با محتوای متفاوت را در برنامه ما فراهم می کنند. ممکن است از یک modal برای نمایش یک متن ساده استفاده کنیم، و علاوه بر این ممکن است بخواهیم از modal مذکور به همراه یک فرم برای ارسال یک درخواست نیز بهره ببریم. اگر چه این ابزارها برای ساخت یک کامپوننت کافی هستند، اما برای  استفاده از html در درون این ابزارها باید از v-html استفاده کنیم تا بتوانیم آنها را رندر کنیم.

در اینجا ما برای slot موردنظر یک نام انتخاب کردیم تا بتوانیم در هر کامپوننت بیش از یک slot داشته باشیم. بعد از اینکه slot ها را نامگذاری کردیم، هر چیزی که با این نام مشخص می شود به جای slot اصلی رندر خواهد شد- در حقیقت می توانید آنرا مانند یک placeholder در نظر بگیرید. همانند placeholder ها، در یک slot می توان در صورتی که هیچ محتوایی درون آن قرار نگیرد، از یک محتوای پیش فرض استفاده کرد. چون محتوایی که در آن قرار می گیرد جایگزین تگ <slot> می شود.

حال بیایید یک سری مقادیر پیش فرض، عناصر کپسوله کننده (wrapper) و کمی استایل css را برای slot ها تنظیم کنیم تا شبیه یک modal ساده به نظر برسد.

<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 tile!

          <button
            type="button"
            class="btn-close"
            @click="close"
          >
            x
          </button>
        </slot>
      </header>
      <section class="modal-body">
        <slot name="body">
          I'm the default body!
        </slot>
       </section>
       <footer class="modal-footer">
          <slot name="footer">
            I'm the default footer!

            <button
              type="button"
              class="btn-green"
              @click="close"
            >
              Close me!
          </button>
        </slot>
      </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 {
    border-bottom: 1px solid #eeeeee;
    color: #4AAE9B;
    justify-content: space-between;
  }

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

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

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

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

و همان طور که می بینید توانستیم یک modal ساده با هم ایجاد کنیم.

افزودن transition

تا به حال به یک modal  که به صورت ناگهانی باز می شود دقت کرده اید؟ اینکار را می توان توسطtransition  ها انجام داد. Vue یک کامپوننت توکار به نامtransition  دارد که ما اجازه می دهد برای باز و بسته شدن یک عنصر transition و انیمیشن تعیین کنیم. این کامپوننت توکار می تواند برای هر نوع عنصر یا کامپوننتی استفاده شود و همچنین می توانید درون آنها از css و جاوا اسکریپت استفاده کنید.

هر زمان که یک کامپوننت یا عنصری که توسط یکtransition  کپسوله شده ، اضافه یا حذف شود، vue  چک می کند که آیا عنصر مورد نظر یک css transition دارد یا نه؟ و آنرا در زمان درست اضافه یا حذف می کند. اینکار با استفاده از جاوا اسکریپت هم انجام می شود، اما دراین آموزش ما از css استفاده می کنیم.

وقتی که یک عنصر اضافه یا حذف می شود، شش کلاس برای transition های ورود و خروج افزوده می شود.هر کدام از آنها توسط یک پیشوند به همراه نام transition مشخص شده اند. در این مقاله شما جزئیات بیشتری از چگونگی کارکرد transition ها را می توانید مشاهده کنید.

در ابتدا می خواهیم  یک کامپوننت توکار transition به modal خود اضافه کنیم.

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

اکنون یک transition برای کار با میزان شفافیت اضافه می کنیم و به آرامی عنصر مورد نظر را توسط کلاس های اعمال شده به آن محو می کنیم.

<style>
 .modal-fade-enter,
  .modal-fade-leave-active {
    opacity: 0;
  }

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

حال می بینید که modal ما به نرمی باز و بسته می شود.

افزودن قابلیت دسترسی به modal

حال تنها کاری که باید انجام شود تبدیل اینmodal  به یکmodal  قابل دسترس است که این کار را توسط ویژگی aria انجام می دهیم.

با افزودن role=”dialog” مشخص می کنیم که کامپوننت ما یک dialog  است که کد آن از کد رابط کاربری جدا شده است. اگر چه افزودن role=”dialog” لازم است، اما برای دسترس پذیر کردنmodal   کافی نیست، همچنین ما باید آنرا به درستی برچسب گذاری کنیم. این کار را با خاصیت های aria-labelledby و  aria-describedby انجام می دهیم. نباید فراموش کنیم که برای دکمه close هم این label ها را اضافه کنیم.

نسخه نهایی کامپوننتmodal  باید مانند زیر باشد:

<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!

            <button
              type="button"
              class="btn-close"
              @click="close"
              aria-label="Close modal"
            >
              x
            </button>
          </slot>
        </header>
        <section
          class="modal-body"
          id="modalDescription"
        >
          <slot name="body">
            I'm the default body!
          </slot>
        </section>
        <footer class="modal-footer">
          <slot name="footer">
            I'm the default footer!

            <button
              type="button"
              class="btn-green"
              @click="close"
              aria-label="Close modal"
            >
              Close me!
            </button>
          </slot>
        </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 {
    border-bottom: 1px solid #eeeeee;
    color: #4AAE9B;
    justify-content: space-between;
  }

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

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

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

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

بکارگیری کامپوننت modal در پروژه

خب حالا می توانیم از کامپوننت modal در پروژه خود استفاده کنیم.

<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>

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

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

برای نمایش نمونه دمو (پیشنمایش) برنامه روی لینک سایت کداپن codepen کلیک کنید.

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.