VueJS’de props yerine attribute kullanarak datayı güncellemek
Kısa bir süredir VueJS kullanıyorum. Karşılaştığım ve çözebildiğim bazı sorunları buradan paylaşacağım. Eğer daha iyi bir çözümünüz varsa lütfen yorum olarak yazın, seve seve kabul ederim.
Malum; VueJS’de props (properties), data ve computed başlıkları altında üç tip veri bulunuyor. Bunlarda props altında tanımlananlar component’i çağırırken setleyebildiğimiz ve içerde değiştirmeye kalktığımızda hata aldığımız veri yöntemidir. Yani bunlar bir kereye mahsus setlenmeli ve daha ellenmemeli. Nedenini dökümantasyonunda anlatmış ama benim ingilizcem ancak anlamaya yetiyor, ne dediğini siz buyurun şurdan okuyun:
In some cases, we may need “two-way binding” for a prop. Unfortunately, true two-way binding can create maintenance issues, because child components can mutate the parent without the source of that mutation being obvious in both the parent and the child.
Örnek komponentimiz şu şekilde olsun:
<template> <div></div> </template> <script> export default { props:["showType","paging"], data(){ result{ items:[] } }, computed:{ total(){ return items.length; } } } </script>
Komponenti kullanırken props’ları şu şekilde setleyebiliyoruz.
<example-component showType="list" :paging="true" ></examle-component>
Burada example-component adıyla register edilmiş komponenti kullanırken “showType” ve “paging” olmak üzere iki ayrı props’u setliyoruz. Ancak biri doğrudan string olduğu için onu showType=”list” şeklinde setleyebilirken, diğeri boolean olabilmesi için :paging=”true” şeklinde setliyoruz. İfadenin başındaki (:) işareti, çift tırnak içinde kalan kısmın javascript ifadesi olduğunu belirtiyor. Örneğin :adet=”10+5″ yazsaydık adet props’unu “15” olarak setlemiş olacaktık.
Bu örnekte, eğer komponentin içerisinde showType’ın değerine göre farklı davranacak bir mekanizma olsaydı; örneğin iki buton olup, birine basınca showType=”list”, diğerinde de showType=”card” setleyebilseydik, komponentte ona göre davransaydı güzel olurdu. Ancak bu senaryoyu yapabilmek için showType’in props değil, data kısmında tanımlanmış olması gerekiyor. Fakat data’daki bir değeri de komponenti kullanırken setleyemiyoruz.
Çözüm?
Birden fazla çözüm var. Örneğin props’da “showType” varsa, data kısmında da “type” isminde bir değişken tanımlayıp, component ayağa kalktığında -yani mounted() fonksiyonu içinde- this.type=this.showType diyebiliriz. Fakat bu ekstra, tek atımlık bir değişken tanımlamak oluyor. Ben bu çözümü çok kullandım ama beğenmedim. Her iki alana aynı değişken adı kullanabilseydik yine severdim ama haliyle bu çakışmaya VueJS izin vermiyor.
İşte yazının başlığındaki yöntem burada devreye giriyor. VueJS’de komponenti kullanırken herhangi bir tanımı yapılmamış bir “attribute” kullanabiliyoruz.
Örneğin;
<example-component view="list"></example-component>
şeklinde aslında hiç tanımı yapılmamış “view” attribute’ünü (props gibi ama tanımı yapılmadığı için buna attribute diyebiliriz ancak) setlemiş olduk. Buna komponent içerisinde this.$attrs.view şeklinde erişebiliyoruz. Burada kullandığımız isim ile props, data veya computed altında tanımladığımız değişkenler çakışmıyor. Çünkü doğrudan değil this.$attrs üzerinden erişiyoruz.
Kendi orijinal örneğimizin son hali şöyle oluyor:
<template> <div></div> </template> <script> export default { props:["paging"], data(){ result{ showType:'card', items:[] } }, computed:{ total(){ return items.length; } } mounted():{ this.showType=this.$attrs.showType } } </script>
Böylece komponent yüklendiğinde this.$attrs içerisinde gelen showType değerini data’da tanımladığımız showType’a aktarmış olduk. Data içerisinde olduğu için komponenti kullanırken dinamik olarak bu değişkeni artık setleyebiliriz.