Vue.js Computed, Method, Watch Kullanımı
Vue.js yazı serisi çerçevesinde, direktiflerin (directives) ardından, daha kapsamlı ve kapsayıcı bir konu olan computed property (hesaplanan özellik), methods (metot/yordam/yöntem) ve watch (izleme) detaylarına geçebiliriz.
Öncelikle metot (method) ile ilgili bir kısa not eklemek istiyorum. Metotlar , uygulamalarda bir işlem gerçekleştirmek için kullanılan kod parçacıklarıdır1 2.
Computed, Methods ve Watch
Hesaplanan özellikler (computed property / computed prop) ve metotlar (method), benim için temel mantığını kavramanın biraz zaman aldığı konular oldular. Neyseki Vue.js dokümantasyonu3 4 ve eğitimlerdeki örnekler süreci (computed property, methods ve watch ilişkileri, benzeştikleri alanlar ve farklılıkları gibi) oldukça kolaylaştırdılar. Gelelim computed
konusuna. Vue Lifecycle dahilinde yer alan computed, render işlemi tamamlandıktan sonraki andır ve computed
adında bir metot oluşturup kullanırız. Metotları ise component içeriğinde, istediğimiz anda çağırabiliriz. Lifecycle konusuna ayrıca değineceğiz. Şimdilik, computed
ile ilgili detaylarda bu hususu aklınızda tutmanızda fayda var.
Vue.JS Computed Property Kullanımı
Mustache syntax kullanımına sıklıkla yer vermeye çalıştım ve hatta bazı örnekler içerisinde işlemler de barındıracak kullanımlara yer verdim ve bu yöntemin çok önerilmediğini de ekledim. Genel bir toparlama yapmak adına ilgili işleme tekrar bakalım.
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
Yukarıdaki kullanımda, message
alındığında bir dizi işlemden geçirilmekte; split()
ile parçalara ayrılmakta, reverse()
ile karakterlerin yerleri değiştirilmekte ve join()
ile yerleri değiştirilen karakterler birleştirilmekte. Sonuç olarak, message
tanımı, örneğin data { message: 'Hello' }
olsun, olleH
haline getirilerek ekranda gösterilmekte. Kapsamlı bir yapı içerisinde, template oluştururken veya düzenlerken bu ve benzeri kullanımlar kontrolü güç bir hale gelebilir. Bu tür durumlarda, gerekli işlemler computed
içerisinde kolaylıkla tanımlanabilirler. Aynı işlemi şimdi yeniden ele alalım.
// Vue v2.x
var app = new Vue({
el: '#message',
data: {
message: 'Hello'
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('')
}
}
});
// Vue v3.x
const app = {
data() {
return {
message: 'Hello'
}
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
}
Vue.createApp(app).mount('#message');
// ya da
Vue.createApp({
data() {
return {
message: 'Hello'
}
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
}
}).mount('#message');
Çıktımızın aynı olmasına karşın, önceki kullanımdan farklı olarak HTML etiketi içerisinde message
yerine reversedMessage
kullanmamız gerekmekte. Bu sayede, artık veri değiştikçe ilgili alanın da değiştiğini görebiliriz.
Computed property ile template içerisinde normal property işlemlerinde olduğu gibi data-bind işlemleri yapmak mümkün. Çünkü, Vue örnek üzerinden anlatmak gerekirse, computed olarak tanımlı reversedMessage
ile message
öğesi birbirine bağlı. Bu sayede message
değiştiğinde reversedMessage
ve ona bağlı olan tüm alanlar da güncellenir. Bu bağımlılık bildirimsel olarak (declaratively) gerçekleştirilir.
Unutmadan, computed property
ön tanımlı olarak getter
tanımlıdır. Ancak, ihtiyaç halinde setter
tanımlanabilmektedir; { get: Function, set: Function }
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ya da
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
Console üzerinden fullName = 'John Doe'
tanımı yaptığımızda setter firstName
ve lastName
için de güncelleme geçecektir.
Computed Property İle Methods Karşılaştırması
v-model direktifi açıklamasında da bahsi geçtiği üzere computed
ve methods
‘un işlev anlamında örtüştüğü noktalar olsalar da temel ve aslında önemli bir farklılık da mevcut5. computed property
bağlı olduğu değişkeni ekranda sunarken ön belleğe (cache) de alır ve bu değişken değişmediği sürece tekrar hesaplama yapmaz. method
kullanımında ise hesaplama yinelenir ve son değer ön bellekleme olmadan ekrana yansıtılır. Özetle, method
re-render gerçekleşen her durumda yeniden çalıştırılır, ancak computed kapsamındaki işlemler yinelenmez. Şimdi, yukarıdaki örneğimizi method ile tekrar oluşturalım.
<p>{{ reverseMessage() }}</p>
veya
<p v-text="reverseMessage()"></p>
methods: {
reverseMessage() {
return this.message.split('').reverse().join('')
}
}
Tanımlandığı alan dışında, yazımda herhangi bir farklılık olmadı ve ekrana yansıyan ifade de aynı.
Computed Property İle Watched Property Karşılaştırması
VueJS, data değişikliklerini gözlemlemek ve bunlara tepki vermek için watch properties olarak ifade edilen daha genel bir yola daha sahiptir. Lifecycle içerisinde watch
component var olduğu sürede, o component içeriğindeki datalarla ilgili değişiklikleri yakalamızı sağlar. Örneğin, bir veri bir başka veriye bağlı ise ve bağlı olduğu veride değişiklik söz konusu olmuşsa watch
(watcher / watched prop) kullanımı tercih edilebilir. Şöyle bir örneğimiz olsun;
<div id="app">
<p v-html="welcome"></p>
<ul>
<li>Name: <strong>{{ firstName }}</strong></li>
<li>Surname: <strong>{{ lastName }}</strong></li>
<li>Full Name: <strong>{{ fullName }}</strong></li>
</ul>
</div>
<script>
// Vue 2.x
var app = new Vue({
el: '#app',
data: {
message: `It's a New Day!`,
firstName: 'John',
lastName: 'Doe',
fullName: 'John Doe'
},
computed: {
welcome() {
return 'Hello' + ' <strong>' + this.fullName + '</strong>, ' + this.message
}
},
watch: {
message(val) {
this.message = val
},
firstName(val) {
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
this.fullName = this.firstName + ' ' + val
}
}
});
// Vue 3.x
const app = Vue.createApp({
data() {
return {
message: `It's a New Day!`,
firstName: 'John',
lastName: 'Doe',
fullName: 'John Doe'
}
},
computed: {
welcome() {
return 'Hello' + ' <strong>' + this.fullName + '</strong>, ' + this.message
}
},
watch: {
message(val) {
this.message = val
},
firstName(val) {
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
this.fullName = this.firstName + ' ' + val
}
}
}).mount('#app');
</script>
Console üzerinden app.lastName = 'Wick'
tanımı yapalım. Bu durumda hem fullName
hem de message
içeriğinin değiştiğini görebilirsiniz. Watch
alanını temizleyip aynı işlemi gerçekleştirdiğinizde sadece ilgili veri alanı güncellenecektir6.
Özetlemek gerekirse, computed properties
diğer verilerden türetilmiş yeni veriler oluşturmak istendiğinde öne çıkmaktadır7. Bu verileri dönüştürmek (transform), filtrelemek (filter) ya da değiştirmek (manipulate) istediğimizde rahatlıkla kullanabiliriz. Computed properties
her zaman bir değer döndürmek (return) ve eş zamanlı olmak durumundadır. Diğer yandan, bir bileşenin (component) prop
aldığını ve bu prop içeriğinin her değişmesi durumunda bir AJAX isteği gerçekleştirilmesi gerektiğini düşünün. Bu durumda Watch property
ile verideki değişikliği izlemek çok daha isabetli bir karar olacaktır8. Özetlemek gerekirse asynchronous ve bütçeli operasyonlardaki veri değişikliklerinin takibinde watch
değerlendirilebilir bir seçenektir9 10.
- JavaScript Object Methods. W3Schools ↩
- What is Method, Property and Function? StackOverflow ↩
- Vue.js API. v2.x ↩
- Vue.js API. v3.x ↩
- Method vs Computed in Vue. StackOverflow ↩
- VueJs, difference between computed property and watcher? StackOverflow ↩
- Michael Thiessen. (2018). Computed Props and Watchers — What's the Difference? ↩
- VueJs, difference between computed property and watcher? StackOverflow ↩
- Computed Properties and Watchers. Vue 2.x ↩
- Computed Properties and Watchers. Vue 3.x ↩