تبدیل عناصر مختلف به یکدیگر با انیمیشن

Convert Different Elements to Each Other with Animation

Vue.JS 2: تبدیل عناصر مختلف به یکدیگر با انیمیشن - قسمت 62

تا این قسمت از کار یکی از عناصر را با انیمیشن ظاهر کرده و سپس همان را خارج می کردیم اما در بسیاری از اوقات می خواهیم کار دیگری را انجام بدهیم. در بسیاری از اوقات لازم است که هم زمان با مخفی شدن یک عنصر، عنصر دیگری ظاهر شود. به عبارت دیگر به جای تعریف انیمیشن برای حذف یا نمایش عنصر، نیاز به تعریف انیمیشن برای تبدیل عناصر به یکدیگر داریم.

برای شروع این جلسه به فایل App.vue رفته و از transition دارای alertAnimation یک کپی بگیرید. همچنین به قسمت style ها رفته مدت زمان transition را در slide-leave-active از سه ثانیه به یک ثانیه تغییر دهید تا همه چیز مرتب و بدون مشکل باشد:

.slide-leave-active {
  animation: slide-out 1s ease-out forwards;
  transition: opacity 1s;
  opacity: 0;
}

سپس برای transition:

<transition :name="alertAnimation">
  <div class="alert alert-info" v-if="show">This is some Info</div>
</transition>
<transition name="slide" type="animation">
  <div class="alert alert-info" v-if="show">This is some Info</div>
</transition>
<transition appear enter-active-class="animated bounce" leave-active-class="animated shake">
  <div class="alert alert-info" v-if="show">This is some Info</div>
</transition>
<transition :name="alertAnimation">
  <div class="alert alert-info" v-if="show">This is some Info</div>
</transition>

حالا مجموعا چهار transition داریم. برای اینکه بتوانیم با انیمیشن دو عنصر را به یکدیگر تبدیل کنیم حداقل به دو عنصر نیاز داریم بنابراین در transition تازه کپی شده یک div دیگر ایجاد می کنیم:

<transition :name="alertAnimation">
  <div class="alert alert-info" v-if="show">This is some Info</div>
  <div class="alert alert-warning" v-if="!show">This is some Warning</div>
</transition>

همانطور که مشاهده می کنید ما دو div مختلف درون این transition داریم: اولی، کلاس info و دومی، کلاس warning دارد. قبلاً هم توضیح داده بودم که درون transition ها فقط یک عنصر با یک شرط جا می گیرد و اگر بخواهیم چند عنصر را درون یک transition داشته باشیم باید شرط آن ها با هم یکی نباشد (در ادامه دوره، راه حل استفاده از transition برای چندین عنصر با یک شرط واحد را نیز توضیح می دهیم اما فعلاً بحث ما مربوط به این موضوع نیست) به همین دلیل شرط div دوم را برعکس شرط اول گذاشته ام.

نکته: کد بالا با v-show کار نمی کند چرا که v-show عنصر را از DOM حذف نکرده و فقط آن را با display: none مخفی می کند. در این صورت باز هم دو عنصر درون transition خواهیم داشت و باعث خطا می شویم.

البته برای زیبا تر شدن کدها می توانیم به جای دو v-if، از v-else نیز استفاده کنیم:

<transition :name="alertAnimation">
  <div class="alert alert-info" v-if="show">This is some Info</div>
  <div class="alert alert-warning" v-else>This is some Warning</div>
</transition>

شاید تصور کنید که با باز کردن مرورگر همه چیز حل می شود اما اینطور نیست. در حال حاضر دو کادر ما به هم تبدیل می شوند اما هیچ fade یا انیمیشن دیگری مشخص نیست و تبدیل شدن آن ها به صورت آنی انجام می شود. دلیل این مشکل چیست؟ اگر برای چنین شرایطی از یک عنصر دو بار استفاده کنیم (مثل کد بالا که دو div داریم) Vue نمی تواند بین آن ها تفاوت قائل شود. از نظر Vue هر دو div در کد بالا یکی هستند بنابراین فقط محتوای آن ها را با هم عوض می کند و طبیعتا انیمیشنی نمایش داده نمی شود. برای این که کلاس های انیمیشن به صورت صحیح روی عناصر اعمال شوند، باید خود عناصر تغییر کنند نه محتوایشان.

 برای حل این مشکل باید برای هر کدام از این دیوها key (به معنی کلید) تعریف کنیم. این key شناسنامه این دیوها است و مشخص می کند که این دو با یکدیگر تفاوت دارند:

<transition :name="alertAnimation">
  <div class="alert alert-info" v-if="show" key="info">This is some Info</div>
  <div class="alert alert-warning" v-else key="warning">This is some Warning</div>
</transition>

اگر کدهای بالا را ذخیره کرده و به مرورگر بروید شاهد مشکل دیگری خواهید بود. مشکل جدید این است که کادر دوم، قبل از حذف شدن کادر اول به صفحه اضافه می شود و به همین دلیل شاهد یک جهش بین این دو کار هستیم. این جهش باعث می شود ظاهر برنامه بسیار زشت شود.

اگر این دو عنصر را position: absolute تعریف کرده بودیم هر دو عنصر روی یکدیگر قرار می گرفتند و دیگر شاهد این جهش نبودیم اما ما نمی خواهیم position کادرهای خود را تغییر دهیم. با این حساب راه حل چیست؟ فریم ورک Vue برای این مسئله راه حلی را در نظر گرفته است؛ ما باید mode یا حالت transition را تغییر دهیم. ما دو مقدار برای خصوصیت mode داریم:

  • out-in: این گزینه به Vue می گوید بگذار ابتدا عنصر قبلی کاملا حذف شود و سپس به عنصر بعدی اجازه نمایش بده.
  • in-out: این گزینه به Vue می گوید ابتدا عنصر جدید را نمایش بده و سپس عنصر قبلی را حذف کن.

برای کاری که ما می خواهیم انجام دهیم، out-in مشکل را حل می کند:

<transition :name="alertAnimation" mode="out-in">
  <div class="alert alert-info" v-if="show" key="info">This is some Info</div>
  <div class="alert alert-warning" v-else key="warning">This is some Warning</div>
</transition>

حالا اگر مرورگر را باز کنید (npm run dev در حال اجرا باشد) می بینید که کادر آخر با کلیک روی دکمه Show Alert بین info و warning جا به جا می شود.

تا این قسمت از کار از CSS برای ایجاد انیمیشن استفاده کرده ایم اما می خواهم بدانید که می توانیم با جاوا اسکریپت نیز این کارها را انجام بدهیم. در واقع کامپوننت <transition> که تا به حال با آن کار کرده ایم، دارای event هایی است که می توانیم به آن ها گوش کنیم. این event ها به شکل زیر هستند:

  • در حالت اولیه پس از اضافه شدن عنصر به DOM رویدادی به نام before-enter ارسال (emit) می شود.
  • پس از آن رویداد enter ارسال (emit) می شود که مسئول نمایش انیمیشن است.
  • پس از آنکه اجرای انیمیشن تمام شد، رویداد after-enter ارسال (emit) می شود.
  • اگر قبل از تمام شدن اجرای انیمیشن، شرط نمایش آن تغییر کند و انیمیشن کنسل شود، رویداد after-enter-cancelled ارسال می شود.
  • در هنگام شروع عملیات حذف عنصر از DOM رویداد before-leave ارسال می شود.
  • در هنگام اجرای انیمیشن حذف عنصر، رویداد leave ارسال می شود.
  • پس از اتمام انیمیشن حذف، رویداد after-leave ارسال می شود.
  • اگر انیمیشن حذف یا خروج به دلیلی کنسل شود، رویداد after-leave-cancelled اجرا خواهد شد.

به این رویدادها Transition JS Hook می گوییم، یعنی هوک هایی جاوا اسکریپتی که به transition مربوط هستند. در جلسه بعد به صورت عملی با آن ها کار خواهیم کرد.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش رایگان Vue js از صفر تا صد توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (4 دیدگاه)

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

احمد
14 آبان 1399
سلام میشه آموزش رو ادامه بدید؟

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

سادات
10 آبان 1399
سلام خسته نباشید این دوره درحال تکمیل هست؟ تاریخ حدودی اتمام دوره مشخص است یا خیر؟

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

محمد
20 مهر 1399
سلام پس چرا ادامه ندادین آموزش خیلی عالی و عمیقی هست

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

Mehdi
19 مهر 1399
سلام و وقت بخیر لطفا در رابطه با ویژگی های جدید vue3 هم اموزش هایی قرار بدید متشکرم

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