انیمیشن با v-for (Animations with v-for)
می خواهی فهرست هایت قشنگ جان بگیرند؟ با «انیمیشن با v-for» و کامپوننت «TransitionGroup» هر آیتم، ورود و خروج نرمی دارد. «TransitionGroup» یک ظرف ویژه است که عناصر ساخته شده با v-for را جداگانه انیمیت می کند.
معرفی TransitionGroup
کامپوننت <TransitionGroup> دور عناصر v-for می نشیند و برای هر آیتم انیمیشن جدا می سازد. «کلید (key)» شناسه یکتا است؛ با آن Vue هر آیتم را درست دنبال می کند.
نمونه پایه با tag و key
<TransitionGroup tag="ol">
<li v-for="x in products" :key="x">
{{ x }}
</li>
</TransitionGroup>
استایل های ورود با کلاس های v-*
<style>
.v-enter-from {
opacity: 0;
rotate: 180deg;
}
.v-enter-to {
opacity: 1;
rotate: 0deg;
}
.v-enter-active {
transition: all 0.7s;
}
<\/style>
افزودن آیتم ها با انیمیشن
با افزودن هر نام تازه به آرایه، آیتم جدید با انیمیشن وارد می شود. مثل اضافه کردن دانش آموز جدید به صف، اما با ورود نرم.
App.vue: افزودن محصول جدید
<template>
<h3>The <TransitionGroup> Component</h3>
<p>New products are given animations using the <TransitionGroup> component.</p>
<input type="text" v-model="inpName">
<button @click="addEl">Add</button>
<TransitionGroup tag="ol">
<li v-for="x in products" :key="x">
{{ x }}
</li>
</TransitionGroup>
</template>
<script>
export default {
data() {
return {
products: ['Apple', 'Pizza', 'Rice'],
inpName: ''
};
},
methods: {
addEl() {
const el = this.inpName;
this.products.push(el);
this.inpName = null;
}
}
};
<\/script>
<style>
.v-enter-from {
opacity: 0;
rotate: 180deg;
}
.v-enter-to {
opacity: 1;
rotate: 0deg;
}
.v-enter-active {
transition: all 0.7s;
}
<\/style>
حذف آیتم ها و جابجایی بقیه
اگر وسط فهرست حذف کنی، بقیه باید جای خالی را پر کنند. بدون تنظیم درست، ناگهانی می پرند. با کلاس «v-move»، حرکتشان نرم می شود.
App.vue: بدون v-move (پرش ناگهانی)
<template>
<h3>The <TransitionGroup> Component</h3>
<p>New products are given animations using the <TransitionGroup> component.</p>
<button @click="addDie">Roll</button>
<button @click="removeDie">Remove random</button><br>
<TransitionGroup>
<div v-for="x in dice" :key="x" class="diceDiv" :style="{ backgroundColor: 'hsl(' + x * 40 + ',85%,85%)' }">
{{ x }}
</div>
</TransitionGroup>
</template>
<script>
export default {
data() {
return {
dice: [],
inpName: ''
};
},
methods: {
addDie() {
const newDie = Math.ceil(Math.random() * 6);
this.dice.push(newDie);
},
removeDie() {
if (this.dice.length > 0) {
this.dice.splice(Math.floor(Math.random() * this.dice.length), 1);
}
}
},
mounted() {
this.addDie();
this.addDie();
this.addDie();
}
};
<\/script>
<style>
.v-enter-from {
opacity: 0;
translate: 200px 0;
rotate: 360deg;
}
.v-enter-to {
opacity: 1;
translate: 0 0;
rotate: 0deg;
}
.v-enter-active,
.v-leave-active {
transition: all 0.7s;
}
.v-leave-from {
opacity: 1;
}
.v-leave-to {
opacity: 0;
}
.diceDiv {
margin: 10px;
width: 30px;
height: 30px;
line-height: 30px;
vertical-align: middle;
text-align: center;
border: solid black 1px;
border-radius: 5px;
display: inline-block;
}
<\/style>
فعال کردن v-move و حل پرش
<style>
.v-enter-from {
opacity: 0;
translate: 200px 0;
rotate: 360deg;
}
.v-enter-to {
opacity: 1;
translate: 0 0;
rotate: 0deg;
}
.v-enter-active,
.v-leave-active,
.v-move {
transition: all 0.7s;
}
.v-leave-active {
position: absolute;
}
.v-leave-from {
opacity: 1;
}
.v-leave-to {
opacity: 0;
}
.diceDiv {
margin: 10px;
width: 30px;
height: 30px;
line-height: 30px;
vertical-align: middle;
text-align: center;
border: solid black 1px;
border-radius: 5px;
display: inline-block;
}
<\/style>
مثال بزرگ تر: افزودن، حذف، مرتب سازی
با این نمونه، همه چیز واضح تر می شود. می توانی حذف با کلیک، مرتب سازی، و افزودن تصادفی داشته باشی. فهرست کامل نرم جابجا می شود.
App.vue: dice با کلید یکتا و جابجایی نرم
<template>
<h3>The <TransitionGroup> Component</h3>
<p>Items inside the <TransitionGroup> component are animated when they are created or removed.</p>
<button @click="addDie">Roll</button>
<button @click="addDie10">Roll 10 dice</button>
<button @click="dice.sort(compareFunc)">Sort</button>
<button @click="dice.sort(shuffleFunc)">Shuffle</button><br>
<TransitionGroup>
<div v-for="x in dice" :key="x.keyNmbr" class="diceDiv" :style="{ backgroundColor: 'hsl(' + x.dieNmbr * 60 + ',85%,85%)' }" @click="removeDie(x.keyNmbr)">
{{ x.dieNmbr }}
</div>
</TransitionGroup>
</template>
<script>
export default {
data() {
return {
dice: [],
keyNumber: 0
};
},
methods: {
addDie() {
const newDie = {
dieNmbr: Math.ceil(Math.random() * 6),
keyNmbr: this.keyNumber
};
this.dice.splice(Math.floor(Math.random() * this.dice.length), 0, newDie);
this.keyNumber++;
},
addDie10() {
for (let i = 0; i < 10; i++) {
this.addDie();
}
},
compareFunc(a, b) {
return a.dieNmbr - b.dieNmbr;
},
shuffleFunc(a, b) {
return Math.random() - 0.5;
},
removeDie(key) {
const pos = this.dice.map(e => e.keyNmbr).indexOf(key);
this.dice.splice(pos, 1);
}
},
mounted() {
this.addDie10();
}
};
<\/script>
<style>
.v-enter-from {
opacity: 0;
scale: 0;
rotate: 360deg;
}
.v-enter-to {
opacity: 1;
scale: 1;
rotate: 0deg;
}
.v-enter-active,
.v-leave-active,
.v-move {
transition: all 0.7s;
}
.v-leave-active {
position: absolute;
}
.v-leave-from {
opacity: 1;
}
.v-leave-to {
opacity: 0;
}
.diceDiv {
margin: 10px;
width: 30px;
height: 30px;
line-height: 30px;
vertical-align: middle;
text-align: center;
border: solid black 1px;
border-radius: 5px;
display: inline-block;
}
.diceDiv:hover {
cursor: pointer;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
#app {
position: relative;
}
<\/style>
نکته: همیشه برای آیتم های v-for، ویژگی key بگذار. این کار، ردیابی و انیمیشن را دقیق می کند.
جمع بندی سریع
<TransitionGroup>ظرف انیمیشن های v-for است.- برای هر آیتم، کلید یکتا بده.
- کلاس
v-moveجابجایی بقیه را نرم می کند. position: absolute;در خروج، جا را خالی می کند.- سرعت را با
transitionکنترل کن.
بیشتر بخوان: انیمیشن با v-for، انیمیشن ها در Vue.