Vue.js Direktifleri - 2 (show, if-else, on, bind)
Vue.js Direktifleri – 1 yazısında Vue.js için direktif işlev ve öneminden bahsetmiş, ardından v-text
, v-html
, v-once
ve v-for
üzerinden mümkün olduğu kadar yalın ve açıklayıcı örnekler oluşturmaya çalışmıştım.
Bu yazıda ise direktifler konusunun devamı olarak v-show
, v-if
, v-else-if
, v-else
, v-on
ve v-bind
direktiflerinden bahsedeceğim. Ayrıca, burayı tıklayarak yazı içerisinde bahsi geçen örnekleri Gitlab üzerinden görüntüleyebilirsiniz.
Vue.js v-show, v-if / v-else-if / v-else, v-on, v-bind Direktifleri
Direktifleri mümkün olduğu kadar birbirleriyle olan ilişkileri çerçevesinde anlatmaya ve örnekler içerisinde bir sonraki anlatıma da referans olacak eklemeler yapmaya çalışıyorum. Ancak, dikkat edilmesi gereken konu esasında birbirleri yerine kullanılan direktiflerin tam olarak aynı işlevi göstermediği. Render oluşturma sürecinde, diğer tabir ile kapalı kapılar ardında oldukça kritik olabilecek farklılıklar söz konusu olabiliyor. Bu yazıda bahsi geçecek olan v-show
ve v-if
bunlardan biri. Tıpkı bir önceki yazıda v-text
ve v-html
direktiflerinde olduğu gibi… Bu nedenle Vue.js dokümantasyonuna ve bu dokümantasyon içerisindeki satır arası vurgulara dikkat etmenizi önermekteyim. Gelelim bu yazının içeriğini oluşturacak olan direktiflere…
v-show
Element’in görünürlüğüne CSS display üzerinden müdahale eder; display: block | none
. Direktif ilgili elementin durumu değiştiğinde geçişleri tetikler. Unutmadan, v-show
<template>
ile kullanılamaz ve v-else
ile ilişkilendirilemez. Hemen bir örnek işlem gerçekleştirelim.
JS sekmesinde de göreceğiniz üzere bazı ülkeler1 ve ülkelerin başkentlerine sahibiz2. Amacımız ise bu ülkeleri sıralamak. HTML sekmesine baktığınızda, sıralama (repeater) için v-for
direktifinin kullandığını görebilirsiniz. Ardından v-show
direktifi gelmekte; v-show="index % 2 !== 1"
. v-show
index değerinin 2’ye bölünmediği her li element tekrarını es geçip, diğer durumda display: none
tanımını elemente uygulamakta.
v-show
kullanımında ilişkilendirilen element render edilmiştir. İlgili değerin değişmesi durumunda (true | false) sadece display
işlemi ele alınır. v-if
direktifi içerisinde bu konuya tekrar değineceğim.
v-if / v-else-if / v-else
Yukarıdaki örnekte yer alan 2. listeye (v-if Example) baktığınızda v-if="index % 2 !== 1"
işleminin bizi yine aynı sonuca ulaştırdığını göreceksiniz. Fakat, kaynak kodlara baktığımızda bu defa belirttiğimiz duruma uymayan elementler yerine <!---->
şeklinde yorum satırlarının eklendiğini göreceksiniz.
Evet, v-if
kullanımında render aşamasında belirtilen duruma uymayan elementler render dışında tutulurlar. v-show
ile temel farklılığı işte tam olarak bu! Bu farklılığı maddeler üzerinden ele alacak olursak;
v-if
gerçek bir koşul ifadesidir. Koşul bloğu içerisindeki etkinlik dinleyiciler (event listener) ve alt bileşenler (child component) tamamen kaldırılır ve/veya eklenir.- Bir üst açıklamayla ilişkili olarak,
v-if
ilgili bloğu yeniden oluşturduğu (render) ve/veya yok ettiği içinv-show
‘a göre daha hantaldır. Tabi, diğer yandanv-if
gereksiz yere kullanılmayacak blokların da render edilmemesini sağlar. Dolayısıyla kullanım aşamasında ihtiyaçlar ve olası senaryolara göre tercihte bulunmak daha doğrudur.
Özetle, v-if
‘in daha yüksek toggle maliyeti varken, v-show
‘un daha yüksek render maliyeti vardır. Bu nedenle bir alanı sıklıkla değiştirmek gerekiyor ise v-show
(menu, tab, model vb.), koşulun duruma bağlı ve sık ele alınmayacağı durumlarda ise v-if
(template, oturuma bağlı işlemler, form alanları vb.) tercih edilebilir.
<template v-if="isLoggedIn">
<label> Logout </button>
<button> Logout </button>
</template>
v-if
ile ilgili bir ekleme de v-for
kullanımına dair. Genelde önerilmeyen bu birliktelikte eğer bir gereklilik var ise v-for
‘un v-if
‘ten daha öncelikli değerlendirildiğini3 unutmamalısınız. Diğer yandan, listelemelerde sadece bazı elementlerin render edilmesi isteniyorsa4 bu durum bir avantaj olarak da değerlendirilebilir5.
Örneğin; <li v-for="todo in todos" v-if="!todo.isComplete">{{ todo }}</li>
v-if / v-else-if ve v-else
v-if
, v-else-if
ve v-else
kullanımı ise pek çok programlama dilinde kullanılan, klasik if-else işlemleri için kullanılabilmekte. v-show
altında da belirttiğim gibi v-if
ilişkili olduğu elementin şart dahilinde render dışında tutulmasını sağlar. İlgili şart gerçekleştirildiğinde ise ilgili alanı yeniden oluşturur.
<ul class="ui list">
<li v-if="age < 18">Generation Z, or iGeneration (Teens & younger)</li>
<li v-else-if="age => 18 && age < 35">Millennials, or Generation Y (18 – 34 years old)</li>
<li v-else-if="age => 35 && age < 51">Generation X (Roughly 35 – 50 years old)</li>
<li v-else>Baby Boomers (Roughly 50 to 70 years old)</li>
</ul>
Yukarıdaki listeleme için data
nesnesi (object) içeriğinde age
adında bir key
oluşturalım ve değer olarak 10
verelim. Bu durumda bize Generation Z, or iGeneration (Teens & younger)
dönecektir. İnternet tarayıcınızın console alanından yeni değerler atayarak bize farklı liste elementlerinin cevap verdiğini görebilirsiniz.
v-if
tek başına kullanılabileceği gibi v-else
ile koşul dışındaki alanlara da cevap verilebilir. Farklı koşullar için de elbette v-if-else
ile alternatif koşullar değerlendirilebilir.
v-on
Elemente bir etkinlik dinleyicisi (event listener) ekler. Etkinlik türü, argüman (argument) ile gösterilir. @
şeklinde kısaltılmış bir şekilde kullanılabilir; örneğin @click="..."
. İfade (expression) bir metot (method) veya satır içi ifade (inline statement) olabilir. Normal bir element kullanıldığında, yalnızca native DOM olaylarını dinler. Özel bir element bileşeninde (component) kullanıldığında, v-on
direktifi (emit) alt bileşende (child component) yayılan özel etkinlikleri (custom events) de dinleyecektir. Satır içi ifadelerde, ifade özel $event
özelliğine erişebilir: v-on: click = "handle ('ok', $event)"
. 2.4.0+ sürümünden başlayarak, v-on
ayrıca bir argüman olmadan olay / dinleyici (event/listener) çifti nesnesine (object) bağlanmayı (binding) da destekler. Unutmanda, nesne (object) söz diziminde modifier desteği söz konusu değil. Öncelikle modifier listesine bir bakalım:
.stop
–event.stopPropagation()
metotunu çağırır..prevent
–event.preventDefault()
metotunu çağırır..capture
– Yakalama modunda (capture mode) etkinlik dinleyici ekler..self
– Yalnızca etkinlik bu öğeden gönderilirse (dispatch) işlem gerçekleştirir..{ keyCode | keyAlias }
– Sadece belirli key tanımları için işlem gerçekleştirir..native
– Bileşenin (component) ana elementiye (root) ilgili yerel (native) etkinlikleri dinler..once
– Tek seferlik işlem gerçekleştirir..left
– (2.2.0+) Mouse sol tıklama ile ilişkili olarak etkinlik gerçekleştirir..right
– (2.2.0+) Mouse sağ tıklama ile ilişkili olarak etkinlik gerçekleştirir..middle
– (2.2.0+) Mouse orta tuş tıklama ile ilişkili olarak etkinlik gerçekleştirir..passive
– (2.3.0+) {passive: true} ile bir DOM olayına ilişir.
Örneklerle bu anlatımları pekiştirelim. Aşağıdaki kullanımları ayrıca shorthand @
kullanımlarıyla da belirttim.
// method handler:
<button v-on:click="..."></button>
<button @click="..."></button>
// dinamik etkinlik (event) (2.6.0+) kullanımı:
<button v-on:[event]="..."></button>
<button @[event]="..."></button>
// ifade (expression) olmaksızın doğrudan işlem
<form @submit.prevent></form>
// keyAlias ile Enter tuşu işlemi
<input @keyup.enter="...">
// Tek seferlik tıklama etkinliği
<button v-on:click.once="..."></button>
<button @:click.once="..."></button>
// Mouse etkinliği (object syntax (2.4.0+)):
<button v-on="{ mousedown: ..., mouseup: ... }"></button>
v-bind
v-bind
en kapsamlı ve en çok kullanılan direktiflerden biri6. Kısa yol olarak v-bind
yerine sadece :
kullanılabilir7. Dinamik olarak bir veya daha fazla attribute veya component prop işlemi gerçekleştirebilmemizi sağlamakta. Unutmadan, prop binding işleminde alt komponent içeriğinde prop
tanımlanımlı olması gerekmektedir. .prop
, .camel
ve .sync
modifier’larını ve opsiyonel olarak attrOrProp
argümanını alabilmekte. class
veya style
attribute işlemlerinde array veya object kullanabilmekteyiz. v-bind
, bir argüman olmadan kullanıldığında attribute adı ve değeri içeren bir object ile ilişkilendirilebilir. Yalnız, bu durumda class ve style array ya da object alamaz. Bu açıklamalar tam olarak ne ifade ediyor, bir bakalım.
<a href="https://ceaksan.com/vue-js-v-show-v-if-v-else-if-v-else-v-on-v-bind/"> ... </a>
<a href="https://ceaksan.com/vue-js-v-show-v-if-v-else-if-v-else-v-on-v-bind/"> ... </a>
// görsel için src (attribute) içeriği oluşturma:
<img v-bind:src="...">
<img :src="https://ceaksan.com/vue-js-v-show-v-if-v-else-if-v-else-v-on-v-bind/">
<img :src="https://ceaksan.com/vue-js-v-show-v-if-v-else-if-v-else-v-on-v-bind/">
// dinamik özellik tanımı (key ve value) (2.6.0+):
<button v-bind:[key]="value"></button>
<button :[key]="value"></button>
// class tanımları:
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
// stil tanımları
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="styleObjectA"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
// nesne özelliği
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
// prop modifier ile DOM işlemleri
<div v-bind:text-content.prop="text"></div>
// <!-- prop binding. "prop" must be declared in my-component. -->
<my-component :prop="someThing"></my-component>
// alt bileşen ile prop ilişkisi oluşturma
<child-component v-bind="$props"></child-component>
// XLink.
<svg><a :xlink:special="foo"></a></svg>
<svg :view-box.camel="viewBox"></svg>
v-bind
belirttiğim gibi örneklerde sıklıkla kullanacağımız direktiflerden biri. Bu nedenle kapsamlı örnekleri bir başka yazıda ele alacağım ve gerekli ise -elbette deneyimlerim çerçevesinde- mümkün olduğu kadar açıklamalar eklemeye çalışacağım. Bu süreç içerisinde, basit bir şekilde direktiflerin tekrarı olarak hazırladığım ToDo List uygulamasına göz atabilirsiniz.
Sonuç Olarak
Bu yazıda, v-text, v-html, v-once ve v-for direktiflerinin de devamı olarak, v-show
, v-if
, v-else-if
, v-else
, v-on
ve v-bind
direktiflerinden, v-show
ile v-if
direktiflerinin benzerlik ve farklılıklarından bahsetmeye çalıştım. Örnekler üzerinden direktif özelliklerinin daha da netleştiğini düşünüyorum. Bu nedenle farklı kullanımları da bir arada sunmaya çalışıyorum. Bu anlamda, olası ekleme ve geliştirmeler iletmek isterseniz memnuniyetle yazılara dahil etmek isterim.