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.
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.
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 şekildeHello 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ğerimizfalse
olarak tanımlandığı içinNO
dönüşü alınmakta. - Liste örneğinde
v-for
ile 1’den 10’a kadar bir değer üretmekte ve bu değeriv-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 üretilenn
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 karakterlertoUpperCase()
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.
- Naukri Engineering. (2017). Virtual DOM ↩
- Bartosz Krajka. (2015). The difference between Virtual DOM and DOM ↩
- Render Functions & JSX. Vue v2.x ↩
- Interpolations. Vue v2.x ↩
- Explanation of Different Builds. Vue v2.x ↩
- Netsparker Security Team. (2019). The Cross-site Scripting (XSS) Vulnerability: Definition and Prevention ↩