Vue.js Interpolations (Ara Değerler)

Vue.js işlenen DOM içeriğine müdahale edebilmek için ön tanımlı olarak HTML tabanlı şablon söz dizimi (HTML-based template syntax) kullanmaktadır ve tüm Vue.js şablonları geçerli HTML kuralları çerçevesinde tarayıcılar ve HTML ayrıştırıcılar tarafından rahatlıkla işlenebilir.

AA

Elbette bu işin sadece görünen kısmı. Perde arkasında ise Vue şablonları Virtual DOM render fonksiyonları üzerinden işleme alır. Reaktif sistemle birlikte, Vue, minimum gereksinimleri hesaplayarak (minimum işlem sayısını hesaplayarak) durum değişikliklerini hız/performans bağlamında DOM’a yansıtır1.

Virtual DOM

Eğer Virtual DOM konseptine2 aşina iseniz (örneğin ReactJS de bu özelliği barındırmaktadır) ve Vue.js şablon sistemine alternatif olarak JavaScript‘i yalın bir şekilde kullanmak isterseniz -ki bu konuda bilgili olmadığım için detaylı bir şekilde anlatmam mümkün değil- seçenek olarak sunulan JSX yapısı ile de ilerleyebilirsiniz3. Tabi, hatırlatmakta ayda var. Vue, çoğu durum için HTML şablonlarını önermektedir.

Vue Interpolations (Ara Değerler)

Vue.js’in önerdiği en temel text binding formu mustache sözdizimi ile ifade edebileceğimiz semantic syntax ve declarative syntax ile sağlanmaktadır. Data binding işlemini MVVM temelinde değişkenlerin (mustache.js içeriğinde yer tutucu olarak ifade etmiştik, {{degisken}} şeklinde yazmaktaydık) View’daki data ile render aşamasında yer değiştirmesi olarak özetleyebiliriz4. Vue.js Nedir? başlıklı yazıda {{ message }} içeriğinin instance ile Hello World! değeri ile (app.$data.message) değiştirilmesini sağlamıştık.

// Vue v2.x
const app = new Vue({
  el: '#app',
  data: {
    message: 'Hello World!'
  }
});

// Vue v3.x
const app = Vue.createApp({
  data() {
    return {
      message: 'Hello World!'
    }
  }
}).mound('#app');

Unutmayın, her yer tutucu doğrudan key olarak (örnekteki message bir key ve Hello World! bir value olarak nitelendirilir) belirtilmek durumunda değil. Örneğin, computed properties işlemlerinde de çeşitli ara değerlerden faydalanacağız ve HTML etiketleri içerisinde kullanacağız. Şimdilik yukarıdaki örnek üzerinden ilerleyelim ve Vue’nun yer tutucunu dışında kullanabileceğimiz ve direktif (directive) olarak da ifade edebileceğimiz v-text (declarative syntax) ile v-html‘e bakalım. Ancak, öncesinde JavaScript Expressions konusuna dair birkaç ek örnek daha paylaşmak istiyorum. Ardından, text interpolation içeriğinde matematiksel işlemler ve filtre kullanımı yaparak konuyu sonlandırabiliriz. Unutmadan, v-text ve v-html ve daha pek çok direktifi Vue.JS Direktif Kullanımı başlıklı yazıda örneklerle anlattım. Ayrıca, Vue Kurulum ve Kullanım Yöntemleri başlıklı yazıya da göz atabilirsiniz.

Bu işlemlerde sonraki süreçte Full (Runtime + Compiler) ile devam edeceğim5. Ancak, bilgi olması açısından Compiler gereksinimi olan ve olmayan kullanımları şu şekilde örneklendirebiliriz:

// compiler gerektirir
// Vue v2.x
new Vue({
  template: '<div>{{ message }}</div>'
});

Vue.createApp({
  template: '<div>{{ message }}</div>'
});

// compiler gerektirmez
// Vue v3.x
new Vue({
  render (h) {
    return h('div', this.message)
  }
});

Vue.createApp({
  render (h) {
    return h('div', this.message)
  }
});

Vue Şablon Yapısı İçerisinde JavaScript İfadeleri

Yukarıdaki örnekte message key’i Hello World! değeri almış ve bunu HTML etiketleri içerisindeki {{ message }} alanına aktarmıştı. Fakat mustache içerisindeki alanın yetenekleri sadece string değerlerle sınırlı değil. Basit bir şekilde örneklendirelim.

 <div id="app">

   <h1>{{ message }}</h1>
   <h2>{{ message.split('').reverse().join('') }}</h2>

   <p><strong>5 x {{ number }}</strong> is <span style="color: red;">{{ number * 5 }}</span></p>

   <p>
    Q: Is It private?<br />
    A: {{ private ? 'YES' : 'NO' }}
   </p>

   <ul>
    <li v-for="n in 10" v-bind:id="'list-' + n">{{ number + n }}</li>
   </ul>

   {{ message |  uppercase }}

  </div>

Vue() instance da şu şekilde olsun:

// Vue v2.x
new Vue({
  el: '#app',
  data: {
    message: 'Hello World!',
    private: false,
    number: 10
  },
  filters: {
    uppercase: function(value) {
      return value.toUpperCase()
    }
  }
});

// Vue v3.x
Vue.createApp({
  data() {
    return {
      message: 'Hello World!',
      private: false,
      number: 10
    }
  },
  computed: {
    uppercase(value) {
      return value.toUpperCase()
    }
  }
}).mound('#app');
  • h1 ile başlayalım. {{ message }} temel bir şekilde Hello World! değerini almakta.
  • h2 etiketi içerisindeki ifade ise {{ message }} içeriğinin karakterler temelinde parçalanması (split), sırasının değiştirilmesi (reverse) ve tekrar bir araya getirilmesi (join) işlemlerini barındırmakta. Normal şartlarda bu gibi işlemleri mustache içerisinde değil computed tanımıyla sağlarız. Ancak, bu tür kullanımlara da denk gelmek muhtemel olduğu için örnek olarak ekledim.
  • Bir sonraki örnekte ise number: 10 değeri ile matematiksel işlem yapıldığını görmektesiniz.
  • Q/A alanındaki örnekte de mustache içerisinde (semantic syntax) bir durum/şart işlemi gerçekleştirilmekte. private değerimiz false olarak tanımlandığı için NO dönüşü alınmakta.
  • Liste örneğinde v-for ile 1’den 10’a kadar bir değer üretmekte ve bu değeri v-bind ile ilgili liste elementine id olarak atamaktayız. Sayfanın kaynak kodlarında bu işlemi görebilirsiniz. Ek olarak, liste elementi içeriğinde de üretilen n değerini instance içerisinde belirttiğimiz 10 değerine (number: 10) eklemekteyiz. Böylelikle yer yeri liste elementinde toplama işlemi gerçekleştirilmektedir.
  • Son örnek ise bir filtre kullanımı barındırmakta. {{ message }} içeriğimizi pipe ile filters alanı içerisindeki anonim fonksiyona değer olarak iletmekteyiz. Fonksiyon içerisinde de bu değerdeki tüm karakterler toUpperCase() ile büyük harfe dönüştürülerek döndürülmektedir (return).

Vue v-text ve v-html Direktifleri

İlk olarak v-text direktifini kullanarak yukarıdaki örneği düzenleyelim.

<!DOCTYPE html>
<html>
 <head>
  <title>Vue Example #1</title>
 </head>
 <body>

  <div id="app">
   <h1 v-text="message"></h1>
  </div>

  <script src="https://vuejs.org/js/vue.js"></script>

  <script>
  // Vue v2.x
  new Vue({
    el: '#app',
    data: {
      message: 'Hello World!'
    }
  });

  // Vue v3.x
  Vue.createApp({
    data() {
      return {
        message: 'Hello World!'
      }
    }
  }).mound('#app');
  </script>

 </body>
</html>

v-text elementin textContent özelliğinde (property) değişiklik yapmaktadır. Bu özelliğe JavaScript ile doğrudan document.getElementById("element").textContent; ile ulaşmaktaydık. v-html ise innerHTML (document.getElementById('element').innerHTML) üzerinden işlem yapmaktadır ve bu sayede HTML etiketlerini de kullanabilmekteyiz. Yukarıdaki örneğimizi sadece değişiklik gereken alanlar üzerinden yeniden ele alalım.

<div id="app">
  <h1 v-html="message"></h1>
</div>

<script src="https://vuejs.org/js/vue.js"></script>

<script>
  // Vue v2.x
  new Vue({
    el: '#app',
    data: {
      message: '<a href="https://exoplanets.nasa.gov/milky-way-overlay/">Hello <span style="color: red;">World!</span></a>'
    }
  });

  // Vue v3.x
  Vue.createApp({
    data() {
      return {
        message: '<a href="https://exoplanets.nasa.gov/milky-way-overlay/">Hello <span style="color: red;">World!</span></a>'
      }
    }
  }).mound('#app');
</script>

Dinamik olarak HTML içerikleri oluşturmak XSS (cross-site scripting) gibi açıklara neden olabilir6. Bu nedenle basılacak HTML içeriklerin kullanıcı tarafından sağlanan içeriklerde kullanılmaması ve eğer bir gereklilikse kontrollü bir şekilde uygulanması önerilir.

Attributes (Nitelik / Özellik) Kullanımı

Vue şablon (template) yapısı içerisinde HTML özellikleri (attributes) için mustaches ({{…}}) kullanımına izin vermemektedir. Bunun yerine Vue.js v-bind direktifini sunar.

<div v-bind:id="dinamikId"></div>

Yukarıdaki örnek dinamik bir id oluşturmaktadır. v-bind direktifi oldukça kapsamlı bir kullanıma sahip ve direktifler yazısına göz atabilirsiniz.