Vue.js: الانتقالات والرسوم المتحركة
آخر تحديث: 2026-08-26
تجعل الانتقالات والرسوم المتحركة تطبيق Vue الخاص بك أكثر ديناميكية — حيث تحدث انتقالات سلسة عند دخول العناصر إلى منطقة العرض أو خروجها منها، وإعادة ترتيب أنيقة عند تغير القوائم. يتضمن Vue مكوني <Transition> و<TransitionGroup>، اللذين يعملان مع أسماء فئات CSS أو ربطات JavaScript لتحقيق تأثيرات رسوم متحركة متنوعة.
يُعد إتقان الرسوم المتحركة الانتقالية عاملاً أساسياً في تحسين تجربة المستخدم — فالرسوم المتحركة الجيدة تجعل التطبيق يبدو «سلساً وسريع الاستجابة ومحترفاً».
1. ما ستتعلمه
<Transition>رسوم متحركة للدخول/الخروج من عنصر واحد- 6 ربطات لفئات CSS (v-enter-from / v-enter-active وغيرها)
<TransitionGroup>قائمة الرسوم المتحركة- ربطات جافا سكريبت (@before-enter / @enter وما إلى ذلك)
- دمج مكتبات الرسوم المتحركة التابعة لجهات خارجية (@vueuse/motion، GSAP)
- دمج Animate.css
- 5 سيناريوهات رئيسية من واقع الحياة
2. الإحراج الناجم عن زر «تبديل tag التبويب» الثابت
(1) المشكلة: اختفاء المكونات أو ظهورها فجأة؛ وميض واجهة المستخدم
كان لدى المسؤول عن حساب أليس أداة لتبديل علامات التبويب:
<!-- ❌ The "Broken" Version:v-if Sudden Switch -->
<template>
<button @click="currentTab = 'home'">Home</button>
<button @click="currentTab = 'profile'">Profile</button>
<div v-if="currentTab === 'home'">Home Content</div>
<div v-else-if="currentTab === 'profile'">Profile Content</div>
</template>
تجربة المستخدم:
- يظهر/يختفي فجأة عند التبديل بين علامات التبويب
- لا توجد مؤثرات انتقالية، لذا يبدو الأمر «مزعجًا».
- الافتقار إلى الاحترافية
(2) حل الانتقال في Vue: tag واحدة، 6 فئات
<!-- ✅ Correct Version:Smooth Transition -->
<template>
<button @click="currentTab = 'home'">Home</button>
<button @click="currentTab = 'profile'">Profile</button>
<Transition name="fade" mode="out-in">
<div v-if="currentTab === 'home'" key="home">Home Content</div>
<div v-else-if="currentTab === 'profile'" key="profile">Profile Content</div>
</Transition>
</template>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
تجربة المستخدم:
- ظهور وتلاشي سلس عند التبديل بين علامات التبويب
- انتقال مدته 0.3 ثانية، مما يضفي عليه مظهرًا احترافيًا
- 6 فئات CSS يتم تطبيقها تلقائيًا
(3) الإيرادات
بعد إضافة المؤثرات الانتقالية:
- تجربة المستخدم: من «متعثرة» إلى «سلسة»
- الاحترافية: تحسنت بشكل ملحوظ
- حجم الكود: tag واحدة
<Transition>+ 6 فئات CSS - قابلة للتخصيص: 4 أسماء انتقالات + 3 أوضاع
3. الانتقال: عنصر واحد
(1) الاستخدام الأساسي
<template>
<button @click="show = !show">Toggle</button>
<Transition name="fade">
<p v-if="show">Hello Vue</p>
</Transition>
</template>
<style>
/* 6 CSS classes, Vue Auto-add/Remove */
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
(2) شرح مفصل لـ 6 فئات CSS
| الفئة | شرط التشغيل | الغرض |
|---|---|---|
v-enter-from |
قبل إدراج العنصر | الstatus الأولية |
v-enter-active |
العملية الكاملة لإدراج العناصر | عملية الانتقال |
v-enter-to |
بعد إدراج عنصر | الstatus النهائية |
v-leave-from |
قبل خروج العنصر | الstatus الأولية |
v-leave-active |
يخرج العنصر من العملية بأكملها | عملية الانتقال |
v-leave-to |
بعد مغادرة العنصر | الstatus النهائية |
(3) قواعد تسمية الملفات
<!-- v-bind:name="fade" → 6 classes are .fade-xxx -->
<Transition name="fade">...</Transition>
<!-- Don't write name → Default v-xxx (6 classes are .v-xxx) -->
<Transition>...</Transition>
<!-- News name -->
<Transition :name="transitionName">...</Transition>
(4) 3 أوضاع
<!-- 1. Default Mode:Entry and exit occur simultaneously(Overlap) -->
<Transition name="fade">
<div v-if="show">Content</div>
</Transition>
<!-- 2. out-in:Leave first, then enter(Recommendations,Avoid Overlapping) -->
<Transition name="fade" mode="out-in">
<div v-if="show">Content</div>
</Transition>
<!-- 3. in-out:Enter first, then leave(Rare) -->
<Transition name="fade" mode="in-out">
<div v-if="show">Content</div>
</Transition>
4. 5 أنواع من الرسوم المتحركة في CSS
(1) التدرج في الظهور والتلاشي (الأكثر شيوعًا)
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
(2) الانزلاق
.slide-enter-active, .slide-leave-active {
transition: transform 0.3s;
}
.slide-enter-from {
transform: translateX(-100%);
}
.slide-leave-to {
transform: translateX(100%);
}
(3) تكبير/تصغير
.scale-enter-active, .scale-leave-active {
transition: transform 0.3s;
}
.scale-enter-from, .scale-leave-to {
transform: scale(0);
}
(4) الدوران
.rotate-enter-active {
transition: transform 1s;
}
.rotate-enter-from {
transform: rotate(0deg);
}
.rotate-leave-active {
animation: bounce 0.5s;
}
@keyframes bounce {
0% { transform: scale(0); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
(5) الرسوم المتحركة المركبة
.combo-enter-active, .combo-leave-active {
transition: all 0.3s;
}
.combo-enter-from {
opacity: 0;
transform: translateX(-50px) scale(0.8);
}
.combo-leave-to {
opacity: 0;
transform: translateX(50px) scale(0.8);
}
5. الرسوم المتحركة لقائمة TransitionGroup
(1) الاستخدام الأساسي
<template>
<button @click="add">Add</button>
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.name }}
<button @click="remove(item.id)">×</button>
</li>
</TransitionGroup>
</template>
<script setup>
import { ref } from 'vue'
const items = ref([
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' }
])
function add() {
const id = Date.now()
items.value.push({ id, name: `Item ${id}` })
}
function remove(id) {
items.value = items.value.filter(i => i.id !== id)
}
</script>
<style>
/* 6 classes, However, for list items, enter/leave/move */
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-enter-from, .list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.list-leave-active {
position: absolute; /* Remove from the document flow when leaving */
}
/* Animation when list items move */
.list-move {
transition: transform 0.5s;
}
</style>
(2) نقطة أساسية: .list-move
/* When the position of a list item changes(As sorted),Apply Automatically .list-move */
.list-move {
transition: transform 0.5s;
}
(3) 5 سيناريوهات رئيسية للرسوم المتحركة في القوائم
| المشهد | الرسوم المتحركة |
|---|---|
| إضافة عنصر | ظهور تدريجي + انزلاق لأسفل |
| حذف العنصر | التلاشي + التمرير إلى اليسار |
| الفرز | الانتقال السلس إلى الموضع الجديد |
| التصفية | تلاشي تدريجي للعناصر التي يتم إزالتها، وانتقال سلس للعناصر التي يتم الاحتفاظ بها |
| السحب | تتبع حركة الماوس في الوقت الفعلي |
6. خطافات جافا سكريبت
(1) 8 ربطات جافا سكريبت
<template>
<Transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
@after-leave="afterLeave"
:css="false" <!-- Disable CSS class -->
>
<p v-if="show">Hello</p>
</Transition>
</template>
<script setup>
import gsap from 'gsap'
function beforeEnter(el) {
console.log('Before enter:', el)
}
function enter(el, done) {
gsap.to(el, {
opacity: 1,
y: 0,
duration: 0.5,
onComplete: done // Notification Complete
})
}
function afterEnter(el) {
console.log('After enter:', el)
}
// leave / beforeLeave / afterLeave Similar
</script>
(2) تكامل GSAP (موصى به)
npm install gsap
<template>
<Transition :css="false" @enter="onEnter" @leave="onLeave">
<p v-if="show">Hello GSAP</p>
</Transition>
</template>
<script setup>
import gsap from 'gsap'
function onEnter(el, done) {
gsap.fromTo(el,
{ opacity: 0, y: 50 },
{ opacity: 1, y: 0, duration: 0.5, onComplete: done }
)
}
function onLeave(el, done) {
gsap.to(el, { opacity: 0, y: -50, duration: 0.3, onComplete: done })
}
</script>
7. مكتبات الرسوم المتحركة التابعة لجهات خارجية
(1) دمج Animate.css
npm install animate.css
// main.js
import 'animate.css'
<template>
<Transition
enter-active-class="animate__animated animate__fadeIn"
leave-active-class="animate__animated animate__fadeOut"
>
<p v-if="show">Hello</p>
</Transition>
</template>
(2) @vueuse/motion
npm install @vueuse/motion
// main.js
import { MotionPlugin } from '@vueuse/motion'
app.use(MotionPlugin)
<template>
<div v-motion :initial="{ opacity: 0, y: 50 }" :enter="{ opacity: 1, y: 0 }">
Fade in from below
</div>
</template>
(3) حالات الاستخدام الموصى بها لـ GSAP
| المكتبة | التقييم | مناسب لـ |
|---|---|---|
| الرسوم المتحركة في CSS | ⭐⭐⭐⭐⭐ | انتقالات بسيطة، وتلاشي |
| Animate.css | ⭐⭐⭐⭐ | مجموعة متنوعة من الحركات المتحركة المعدة مسبقًا |
| @vueuse/motion | ⭐⭐⭐⭐ | أسلوب تعريفي، يتكامل جيدًا مع Vue |
| GSAP | ⭐⭐⭐⭐⭐ | خطوط زمنية معقدة، رسوم متحركة قائمة على قوانين الفيزياء |
8. أمثلة كاملة: 5 سيناريوهات انتقالية رئيسية
▶ مثال: 1. 5 أنواع من الرسوم المتحركة في CSS
/* 1. Fade In, Fade Out */
.fade-enter-active, .fade-leave-active { transition: opacity 0.3s; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
/* 2. Slide */
.slide-enter-active, .slide-leave-active { transition: transform 0.3s; }
.slide-enter-from { transform: translateX(-100%); }
.slide-leave-to { transform: translateX(100%); }
/* 3. Zoom */
.scale-enter-active, .scale-leave-active { transition: transform 0.3s; }
.scale-enter-from, .scale-leave-to { transform: scale(0); }
/* 4. Rotation */
.rotate-enter-active { transition: transform 1s; }
.rotate-enter-from { transform: rotate(0deg); }
.rotate-leave-active { animation: spin 0.5s; }
/* 5. Combination */
.combo-enter-active, .combo-leave-active { transition: all 0.3s; }
.combo-enter-from { opacity: 0; transform: translateX(-50px) scale(0.8); }
▶ مثال: 2. شرح مفصل لـ 6 فئات CSS
| الفئة | المشغل |
|---|---|
.fade-enter-from |
قبل إدراج عنصر |
.fade-enter-active |
عملية إدراج العناصر |
.fade-enter-to |
بعد إدراج العنصر |
.fade-leave-from |
قبل رحيل العنصر |
.fade-leave-active |
عملية انطلاق العناصر |
.fade-leave-to |
بعد رحيل العنصر |
▶ مثال: 3. الرسوم المتحركة لقائمة TransitionGroup
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</TransitionGroup>
<style>
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-move { transition: transform 0.5s; }
</style>
▶ مثال: 4. 5 مكتبات رئيسية للرسوم المتحركة من جهات خارجية
| المكتبة | الأمر | قابل للتطبيق |
|---|---|---|
| CSS | لا شيء (مدمج) | بسيط |
| Animate.css | npm i animate.css |
الرسوم المتحركة المعدة مسبقًا |
| @vueuse/motion | npm i @vueuse/motion |
أسلوب إعلاني |
| GSAP | npm i gsap |
خط زمني معقد |
| Motion One | npm i motion |
رسوم متحركة خفيفة الوزن على الويب |
▶ مثال: 5. مرجع سريع لـ 5 أخطاء شائعة
| الخطأ | الأعراض | الحل |
|---|---|---|
| لا يتم تطبيق الانتقال | يختفي العنصر على الفور | إضافة غلاف <Transition> + v-if |
| v-for بدون رسوم متحركة | لا توجد انتقالات بين عناصر القائمة | باستخدام <TransitionGroup> |
| لا تظهر الرسوم المتحركة عند الفرز | تقطع الحركة عند التحرك | إضافة فئة .list-move |
| التبديل المتزامن بين مكونات متعددة | التداخل | إضافة key للتمييز + mode="out-in" |
| الرسوم المتحركة في CSS سريعة جدًّا/بطيئة جدًّا | تجربة مستخدم سيئة | اضبط مدة الانتقال على 0.2–0.5 ثانية |
▶ مثال: 6. 5 سيناريوهات عملية
| المشهد | الرسوم المتحركة |
|---|---|
| التبديل بين علامات التبويب | تلاشي + من الخارج إلى الداخل |
| مربع حوار نمطي | تكبير + تلاشي |
| إضافة/حذف من القائمة | الرسوم المتحركة للقائمة |
| تبديل المسار | تلاشي + انزلاق |
| إشعار منبثق | ينزلق من الأعلى + إغلاق تلقائي |
❓ أسئلة شائعة
<TransitionGroup> يجب تحديد العناصر الفرعية بشكل فريد باستخدام :key؛ وإلا فلن يتم تشغيل الرسوم المتحركة.<router-view v-slot="{ Component }"> + <Transition>. في كل مرة يتغير فيها المسار، يتغير المكون، مما يؤدي إلى تشغيل الانتقال.mode="out-in"?<Transition :css="false" @enter="onEnter"> قم بتعطيل فئات CSS واستخدم «الخطافات» في جافا سكريبت فقط. أو قم بتمكين كليهما (استخدم فئات CSS للتنسيق و«الخطافات» في جافا سكريبت لعمليات الاستدعاء المرتدة).transform وopacity (مع تسريع بواسطة وحدة معالجة الرسومات)؛ (2) تجنب الخصائص التي تؤدي إلى إعادة تخطيط العناصر (العرض، الارتفاع، الموضع العلوي)؛ (3) قلل عدد العناصر التي يتم تحريكها في وقت واحد.enter-active-class="animate__animated animate__fadeIn" لربط أسماء فئات Animate.css بخطافات Vue.📖 ملخص
<Transition>إضافة عنصر واحد أو حذفه؛ تتم إدارة 6 فئات CSS تلقائيًا<TransitionGroup>الرسوم المتحركة للقائمة،.list-moveالفرز- 3 أوضاع: الافتراضي (متداخل) / من الخارج إلى الداخل (موصى به) / من الداخل إلى الخارج
- 5 أنواع من الرسوم المتحركة في CSS: التلاشي التدريجي (Fade In/Out) / الانزلاق (Slide) / التغيير في الحجم (Scale) / الدوران (Rotate) / المزج (Combination)
- 8 من نقاط ربط JS: before-enter / enter / after-enter / before-leave / leave / after-leave
- 5 مكتبات رئيسية تابعة لجهات خارجية: CSS / Animate.css / @vueuse/motion / GSAP / Motion One
- 5 تمارين عملية: التبديل بين علامات التبويب / النوافذ المنبثقة / القوائم / توجيه الطلبات / الإشعارات
📝 تمارين
-
أسئلة أساسية (مستوى الصعوبة: ⭐)
تنفيذ نافذة منبثقة بسيطة تعمل بنظام الظهور التدريجي/الاختفاء التدريجي:
- انقر على الزر لفتح النافذة المنبثقة
- ظهور تدريجي خلال 0.3 ثانية
- انقر لإغلاق (التلاشي التدريجي)
- ظهور وتلاشي القناع الخلفي بشكل متزامن
-
مسائل متقدمة (مستوى الصعوبة: ⭐⭐)
تنفيذ حركة رسومية لقائمة TransitionGroup:
- 5 مهام يجب إنجازها
- ظهور العنصر الجديد تدريجيًا (0.5 ثانية)
- إخفاء العناصر المحذوفة تدريجيًا (0.5 ثانية + position: absolute)
- يتم نقل العناصر الأخرى بسلاسة عند الفرز (.list-move)
-
مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)
تنفيذ نظام «الرسوم المتحركة لانتقال الصفحات» بشكل كامل:
- تأثير تلاشي + انزلاق عند التبديل بين المسارات
- ثلاثة أنواع من الرسوم المتحركة لإضافة العناصر وحذفها وفرزها في قائمة
- تركيبة «التكبير + التلاشي» للنوافذ المنبثقة النموذجية
- الرسوم المتحركة المعقدة للخط الزمني مع تكامل GSAP
- اختبار مقارن لخمس مكتبات رسوم متحركة تابعة لجهات خارجية
- تحسين الأداء (تسريع وحدة معالجة الرسومات + قيد التغيير)