<TransitionGroup> (<TransitionGroup>)
اینجا با «ترنزیشن گروپ (TransitionGroup)» آشنا می شوی. ترنزیشن گروپ یعنی انیمیشن جدا برای هر آیتم لیست. مثل حرکت کارت ها در اپ نمرات.
ترنزیشن گروپ در Vue چیست؟
کامپوننت <TransitionGroup> دور عناصر v-for قرار می گیرد. سپس اضافه شدن یا حذف شدن هر آیتم، جداگانه انیمیت می شود. برای هر آیتم باید ویژگی key یکتا باشد.
اگر prop tag را بدهی، خروجی همان تگ رندر می شود. بدون آن، خود تگ HTML رندر نمی شود. همچنین prop های <Transition> را می پذیرد. علاوه برآن، name و moveClass هم دارد.
نمونه پایه با tag و v-for
لیست مرتب می سازیم و هر <li> با انیمیشن وارد یا حذف می شود.
<template>
<TransitionGroup tag="ol">
<li v-for="x in products" :key="x">
{{ x }}
</li>
</TransitionGroup>
</template>
افزودن و حذف با انیمیشن
آیتم تاس اضافه یا حذف می شود. انیمیشن ورود و خروج اجرا می شود.
<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
حذف که انجام شود، بقیه آیتم ها نرم جابه جا می شوند. کلاس v-move مسئول حرکت است.
<template>
<h3>The <TransitionGroup> Component</h3>
<p>When an item is removed inside the <TransitionGroup> component, other items are animated as they fall into their new positions.</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,
.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>
مرتب سازی، شافل، و حذف با کلید یکتا
هر آیتم شیء با کلید یکتا دارد. می توانی ده آیتم بسازی، مرتب کنی، یا شافل کنی.
<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>
تغییر نام کلاس حرکت با moveClass
می خواهی نام کلاس حرکت سفارشی شود؟ از prop به نام moveClass استفاده کن.
<template>
<h3>The <TransitionGroup> Component</h3>
<p>When an item is removed inside the <TransitionGroup> component, other items are animated as they fall into their new positions.</p>
<button @click="addDie">Roll</button>
<button @click="removeDie">Remove random</button><br>
<TransitionGroup moveClass="good-slide">
<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,
.good-slide {
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>
گام های عملی
- لیست v-for بساز و برای هر آیتم key یکتا بده.
- دور لیست از <TransitionGroup> استفاده کن.
- کلاس های v-enter* و v-leave* را در CSS تنظیم کن.
- برای حرکت میان مرحله ای، از v-move یا moveClass استفاده کن.
نکته: برای سورت، شافل، و حذف همزمان عالی است. اثر حرکت طبیعی تر می شود.
هشدار: مقدار key باید یکتا و پایدار باشد. از اندیس آرایه استفاده نکن.
لینک های داخلی مفید
برای مرور سریع، صفحه ترنزیشن گروپ در Vue و کامپوننت Transition را ببین.
جمع بندی سریع
- <TransitionGroup> برای لیست های v-for است.
- همه آیتم ها انیمیشن مستقل دارند.
- کلید یکتا، کاملاً ضروری است.
- v-move جابه جایی نرم می سازد.
- tag و moveClass خروجی را کنترل می کنند.