Vue.js Transition & Animation Kullanımı

Vue.js ögeler DOM‘a eklendiğinde (inserted), bir güncelleme olduğunda (updated) ya da bir öge DOM’dan kaldırıldığında (removed) çeşitli geçiş efektlerinin de olaya (event) dahil edilmesini mümkün kılmaktadır.

AA

Bu işlemler enter/leave & list transitions1 2 başlığı altında nitelendirilmektedir. Peki, ne tür yeteneklerden faydalanabiliriz?

  • CSS geçişlerini (transitions) ve animasyonları (animations) otomatik bir şekilde uygular.
  • 3. parti CSS animasyon araçları (Animate.css, Velocity.js, vb.]) kolaylıkla entegre edilebilir.
  • DOM, geçişlerde JavaScript aracılığıyla kolaylıkla manipüle edilebilir.

Yukarıdaki maddelere referans niteliğinde, 25-27 Mart 2019 tarihinde, VueConf US 2019‘da (Tampa, Florida, USA) yapılan şu 2 sunumu da paylaşmak isterim3.

Gelelim örnek uygulamalara. Vue yazıları içerisinde, ilk transition (geçiş) kullanımına şurada basit bir şekilde yer vermiştim. Örneğin kaynak kodlarına bakıldığında şu satırlar görülebilir:

<transition name="fade">
  <p v-show="inputMessage">
    Message is: <strong>{{ inputMessage }}</strong>
  </p>
</transition>
...
<transition name="slide-fade">
  <p v-show="textMessage">
    Message is: <strong>{{ textMessage }}</strong>
  </p>
</transition>

Vue, bir kapsayıcı bileşen (wrapper component) ile aşağıdaki bağlamlarda herhangi bir öge (element) ve bileşen (component) için giriş ve çıkış geçişleri sunar:

  • v-if direktifi (conditional rendering)
  • v-show direktifi (conditional display)
  • Dinamik bileşenler (dynamic components)
  • Component root nodes

Bu maddeleri örneklendirelim.

 <section id="app" class="section" v-cloak>
    <div class="container">
      <a class="button is-link" v-on:click="show = !show">Primary</a>
      <hr />
      <transition name="fade">
        <div class="notification" v-if="show">
          <button class="delete" v-on:click="show = !show"></button>
          Primar lorem ipsum dolor sit amet, consectetur
          adipiscing elit lorem ipsum dolor. <strong>Pellentesque risus mi</strong>, tempus quis placerat ut, porta
          nec nulla. Vestibulum rhoncus ac ex sit amet fringilla. Nullam gravida purus diam, et dictum <a>felis
            venenatis</a> efficitur. Sit amet,
          consectetur adipiscing elit
        </div>
      </transition>
    </div>
  </section>
// Vue v2.x
const app = new Vue({
  el: '#app',
  data: {
    show: false
  }
});

// Vue v3.x
const app = Vue.createApp({
  data() {
    return {
      show: false
    }
  }
}).mount('#app');

<transition name="fade"></transition> ile kapsanan alan entering ve leaving süreçlerinde farklı class içerikleri alacaklardır. CSS dosyası içerisinde bu css class içerikleri istenen şekilde düzenlenebilir.

.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}

.fade-enter, .fade-leave-to {
  opacity: 0;
}

Örnekte yer alan butona tıklandığında v-if direktifi içeriği oluşturacak veya kaldıracaktır ve bu süreçte duruma göre ilgili class’lar kapsanan elemente dahil edilecektir. Şimdi, yine aynı örneği slide-fade ile v-show direktifiyle oluşturalım.

<transition name="slide-fade">
  <div class="notification" v-show="show">
    <button class="delete" v-on:click="show = !show"></button>
    Primar lorem ipsum dolor sit amet, consectetur adipiscing elit lorem ipsum dolor. <strong>Pellentesque risus mi</strong>, tempus quis placerat ut, porta nec nulla. Vestibulum rhoncus ac ex sit amet fringilla. Nullam gravida purus diam, et dictum <a>felis venenatis</a> efficitur. Sit amet, consectetur adipiscing elit
  </div>
</transition>

Bu durumda CSS class ve içerikleri şöyle olacaktır.

.slide-fade-enter-active {
  transition: all .3s ease;
}

.slide-fade-leave-active {
  transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}

.slide-fade-enter, .slide-fade-leave-to{
  transform: translateX(10px);
  opacity: 0;
}

Bu iki kullanımda gördüğümüz geçiş class’ları v-enter, v-enter-active, v-leave-to, v-leave-active idi. Bu class’lara topluca bakalım.

Transition Classes

Öncelikle, bir element transition component ile kapsandığında ve inserted/removed sürecinde neler olduğuna bakalım:

  • Vue hedeflenen elementin bir CSS geçişine ya da animasyona sahip olup olmadığını otomatik bir şekilde takip eder. Eğer, var ise CSS geçiş class’larını uygun zamanlarda uygular ve/veya uygulananları kaldırır.
  • Eğer transition component için JavaScript hooks kullanılmışsa uygun zamanlarda bu tanımlamalar çağırılır4 5.
  • Eğer element ve/veya component herhangi bir CSS transition/animation almamışsa veya bir JavaScript hook tanımlanmamışsa insertion ve/veya removal DOM işlemleri hemen bir sonraki adımda/karede (browser animation frame) gerçekleştirilir.

Evet, şimdi ilgili CSS class’lara bakabiliriz. Vue.js toplamda, enter/leave transition için kullanılabilecek 6 class barındırmakta.

  • v-enter, giriş için başlangıç niteliğindedir. Element insert edilmeden önce eklenir ve elementin insert edilmesinin hemen ardından çıkarılır.
  • v-enter-active, aktif durumdur. Tüm giriş (entering) aşaması süresince uygulanır. Element eklenmeden önce eklenir, transition/animation uygulandıktan sonra çıkarılır. Bu class uygulama süresi (duration), gecikme (delay) ve hareket hızı eğrisi (easing curve) tanımlamalarında da kullanılabilir.
  • v-enter-to, giriş (enter) için bitiş durumudur. Element yerleştirildikten sonra, v-enter’ın çıkarılmasının hemen ardından bir frame olarak eklenir ve transition/animation ardından çıkarılır.
  • v-leave, bitiş (leave) başlangıç aşamasındaki durumdur. Leaving transition tetiklendiği anda eklenir ve bir frame sonra çıkarılır.
  • v-leave-active, leave için aktif durumdur. Tüm bitiş (leaving) süresince uygulanır. Leave transition tetiklendiği anda eklenir ve transition/animation bittiğinde çıkarılır. Bu class uygulama süresi (duration), gecikme (delay) ve hareket hızı eğrisi (easing curve) tanımlamalarında da kullanılabilir.
  • v-leave-to, bitiş (leave) için sonlanma adımıdır. Leaving transition tetiklendikten bir frame sonra eklenir (v-leave çıkarıldığı anda) ve transition/animation bittiğinde çıkarılır.

Yukarıda maddeler halindeki süreci bir de görsel üzerinden ifade edelim:

Vue Transition CSS Classes

Unutmadan, yukarıda maddeler ve görsel üzerinden aşama aşama gösterilen CSS class’ler tanımlayıcı olarak görev almaktalar. Örneğin, <transition name="slide-fade">...</transition> şeklindeki bir kapsayıcı geçiş bileşeni (transition component) için kullanılabilecek class’lar (yukarıda bahsi geçen 6 class) **slide-fade**-enter-active, **slide-fade**-leave-active gibi olacaktır. Ek olarak, bu class’lar dışında özelleştirilmiş class’lar da kullanılabilmektedir:

  • enter-class
  • enter-active-class
  • enter-to-class
  • leave-class
  • leave-active-class
  • leave-to-class

Örneğin, animate.css kapsamındaki class’ları enter-active-class ve leave-active-class ile ilişkilendirelim6.

      <transition name="slide-fade" enter-active-class="animated tada" leave-active-class="animated bounceOutRight">
        <div class="notification" v-show="show">
          <button class="delete" v-on:click="show = !show"></button>
          Primar lorem ipsum dolor sit amet, consectetur
          adipiscing elit lorem ipsum dolor. <strong>Pellentesque risus mi</strong>, tempus quis placerat ut, porta
          nec nulla. Vestibulum rhoncus ac ex sit amet fringilla. Nullam gravida purus diam, et dictum <a>felis
            venenatis</a> efficitur. Sit amet,
          consectetur adipiscing elit
        </div>
      </transition>

Vue CSS Animations

Transition (geçiş) kullanımının yanı sıra, bir de animasyonlara (animations) bakalım. Öncelikle, CSS transition kullanımında geçerli olan neredeyse her durum CSS animations için de geçerli. Tek farklılık, v-enter için geçerli. v-enter element eklendikten (inserted) hemen sonra değil, animationend olayından sonra kaldırılır.

Vue Transition-Group

Şimdiye kadar, tekil node’lar ve tek seferde render edilen çoklu node’lar için işlemler yaptık. v-for direktifi ve list işlemlerinde aynı kullanımı tercih ettiğinizde şöyle bir hata alırsınız:

<transition> can only be used on a single element. Use <transition-group> for lists.

Hatada da bahsi geçtiği üzere, bu tür kullanımlarda <transition-group> kullanılması gerekmektedir.

<transition-group name="list" tag="p">
<span v-for="item in items" v-bind:key="item" class="list-item">{{ item }}</span>
</transition-group>

<transition-group></transition-group> kullanımında, kapsanan elementlerin hepsi benzersiz bir key’e (v-bind:key="...") sahip olmalıdır.

Bu yazı nezdinde, son olarak duration tanımından bahsedeceğim. Pek çok durumda Vue otomatik olarak transition işlemlerinin sonlandığını anlayabilmektedir. Yine, Vue ön tanımlı olarak root element’in ilk transitionend ve/veya animationend olayı için bekler. Elbette, sayılan bu işlemlerin istenmediği durumlar söz konusu olabilir. Bu durumda kullanılmak üzere transition component için duration prop tanımı (milisaniye cinsinden) yapılabilmektedir. Hatta, bu tanımlama işlemi spesifik olarak enter ve leave duration için de yapılabilmektedir.

<transition :duration="1000">...</transition>
<transition :duration="{ enter: 500, leave: 800 }">...</transition>

Sonuç Olarak

Vue transition/animation işlemlerinin daha pek çok detayı mevcut. Ancak, yazıyı daha fazla uzatmamak ve diğer özellikleri farklı örneklerle ele almak için yazıyı yine Vue.js dökümanınındaki ilgili bölümü önererek Enter/Leave & List Transitions1 2 burada sonlandırıyorum.