Composition API ve Composable’lar ile Yeniden Kullanılabilir Component’ler Oluşturmak
Tags: vue, webdev, frontend, javascript
Published: 2023-03-29 09:51:35


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ajyxbg9ccuqmzm531cf.png)
Merhabalar, bugün sizlere Teknasyon Tech 26. Online Meetup’da anlatmış olduğum “Creating Reusable Components with the Composition API & Composables” adlı sunumun makalesini paylaşmak istiyorum. Bu yazıda sunumda değindiğim tüm konulara değinmek ve video izlemek yerine okuma yapmayı daha çok sevenler için bir kaynak oluşturmak istedim.

Bu yazıda Vue 3 ile birlikte hayatımıza giren Composition API & Composable’larla sürdürülebilir component’ler nasıl yazılır ve ayrıca Composition API’yi neden kullanmamız gerektiğini ve bunu nasıl doğru bir şekilde kullanabileceğimizi keşfedeceğiz.

Öncelikle Vue 3 öncesinde options API ile birlikte geliştirme yaparken ne gibi sorunlarla karşılaştığımıza ve Vue 3'e neden ihtiyaç duyduğumuza bakalım. Sonrasında ise Vue 3 ile birlikte bu sorunların nasıl çözüldüğünü anlamaya çalışalım. Sunumun sonlarında ise composable’larımızı daha iyi nasıl yazabileceğimize bakacağız.

## Don’t Repeat Yourself (DRY)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2mj83f17lzodqoklw2w.png)

Yazılım geliştirmenin en önemli ilkelerinden biri kendimizi tekrar eden işlerden uzak durmaktır. Kodumuzu yeniden kullanılabilir ve taşınabilir tutmak oldukça önemlidir. Bu sayede geliştirme maliyetini düşürüp ekip halinde daha hızlı ürünler ortaya çıkarabiliriz.

Bu yazıda da amacımız Vue projelerinde kendimizi tekrar eden işlerden nasıl uzak duracağımızı ve bunu Vue 3 ile birlikte daha kolay nasıl yapabileceğimizi göreceğiz.

## Single-File Components

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/olrrzjjwpto2rl8f8ocy.png)

Vue projelerinde .vue uzantılı dosyalar Single-File Components(SFC) olarak adlandırılır. Vue SFC’leri template, logic ve styling’i tek bir dosyada kapsüllememize izin verir. Yani Html, Css ve JavaScript kodlarını tek bir dosyada tutabiliriz. Biz bu yazımızda script kısmına odaklanıp Js kodumuzu sürdürülebilir bir şekilde nasıl yazabileceğimizi ve Business logic’lerimizi nasıl düzenleyebileceğimizi göreceğiz.

## Compisition API’den Öncesi

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9ph9ns4j20ekavri13v.png)

Composition API’den önce Vue projelerinde geliştirmelerimizi Options API ile yapıyorduk. Options API ile birlikte kodlarımızın daha net ve anlaşılır olduğunu düşünüyorduk. Bunun sebebi ise yazacağımız kodun kendi yeri var ve neyi nereye eklememiz gerektiğini biliyorduk(data, computed, methods vb).

Yukarıdaki örnek kod bloğuna baktığımızda kodumuzun oldukça düzenli, okunması ve anlaşılması kolay göründüğünü söyleyebiliriz. Peki gerçekten öyle mi? Küçük projeler için düşünüldüğünde iyi bir çözüm gibi duruyor olsa da bu durumun geliştirilen uygulama küçük ve basit olduğunda geçerli olduğunu söyleyebiliriz.

Uygulama veya component’ler büyüdükçe, özellikle bir component içinde birden fazla logic barındırmaya başladığımızda işler karmaşık hale gelmeye başlıyor. Bir component’te birden fazla logic tuttuğumuzu düşünelim. Bu durumda bu logic’lere ait kodlar hep aynı bloklar içinde yazılacağından kodumuzu güncellemek, yeni bi özellik eklemek veya bi özelliği çıkarmak oldukça zahmetli olacaktır. Hangi method’un hangi logic’e veya hangi data’nın hangi logic’e ait olduğunu tek seferde anlamak oldukça zor olacaktır.

Bu durumda bir logic ile ilgili geliştirme yaparken kodda devamlı yukarı aşağı hareket etmek durumunda kalacak ve kodumuzu belli bi sıraya göre okuyamayacağımızdan kodu anlamak ve geliştirme yapmak zor olacaktır. Bu da kodun okunurluğunu olumsuz etkileyen bir durum olarak karşımıza çıkacaktır.

Bunun yerine kodlarımızı logic’lere göre gruplayabilseydik, ilgili logic ile ilgili çalışırken sadece o logic ile ilgili kodları göreceğimizden ve kodları da kitap okur gibi belli bi düzende okuyacağımızdan kodu anlamak ve geliştirme yapmak çok daha kolay olacaktı. Composition API’nin devreye girdiği yer işte tam olarak burasıdır.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ks5hmpddqexp0b54z9e.png)

Yukarıdaki görselde Options API ile geliştirilen kodun Composition API ile geliştirilen kod ile kıyaslandığında ne kadar karmaşık kaldığını görebilirsiniz. Aşağıdaki kod örneğinde de solda Options API ile yazılan bir kodun Composition API ile nasıl yazılabileceğini görebilirsiniz.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ta1jyozo9mewq7y9kjdd.png)

Özetle Composition API, Logic’lerin gruplanmasını ve kodun sırasıyla ele alınmasını sağlar. Bu sayade bir logic ile ilgili işlem yaparken sadece o logic ile ilgili kodları görürüz. Bunlarla beraber bir logic’i component’ten ayırmak veya yeni bir logic eklemek çok daha kolay olacaktır. Örneğin yukarıdaki kodda Composition API ile yazılmış olan user logic’i başka bir yere taşınmak istendiğinde, logic zaten gruplanmış olduğundan ilgili kodu component’ten çıkarmak çok daha kolay olacaktır.

## Options API İle Birlikte Kendimizi Tekrar Eden İşlerden Uzak Durmak

Tahmin edebileceğiniz üzere Composition API’nin avantajları bunlarla sınırlı değildir. Yazının başında değindiğimiz bir konu vardı. Yazılım geliştirmenin en önemli ilkelerinden biri kendimizi tekrar eden işlerden uzak durmaktır. Kullandığımız diller ve araçlar bizi kendimizi tekrar eden işlerden uzak durmamıza yardımcı olacak çözümler üretirler ve bu çözümler süreç boyunca gelişir ve değişir.

Şimdi Composition API öncesinde yani Options API ile geliştirme yaparken kendimizi tekrar eden işlerden kaçmak için hangi çözümleri kullandığımıza ve bu çözümlerin neden yetersiz kaldığına örneklerle beraber bakalım.

Örneğin bir Component’te kullandığımız bir fonksiyon veya kod bloğunu proje genelinde kullanmak istediğimizde bunu Options API ile nasıl yapıyorduk ve ne gibi sorunlarla karşılaşıyorduk bunlara bakalım. Sonrasında da Composition API ile bu sorunlar nasıl çözülmüş bunlara bakalım.

## Utility Functions

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bmd79chycsgb5d7tg2j0.png)

Bu çözümlerden ilki Utility Function’lardır. Utility Function’lar özetle dışarıdan parametre alabilen ve sonucunda bir değeri return etmesini beklediğimiz, ufak kod bloklarını kapsüllememize olanak tanıyan bir yapıdır. Fakat kullanımları sınırlıdır çünkü vue’ye özgü özellikleri(Reaktif değişkenler, mounted, created vb) bu fonksiyonların içine tanımlayamıyor ve kullanamıyoruz.

Yukarıdaki görseli incelediğimizde increment fonksiyonunun tanımlandığını fakat count reaktif değişkeninin fonksiyon içinde tanımlanamadığından component içinde tanımlandığını görebilirsiniz. Burada count değişkenini de kapsüllemek istediğimizde veya vue’ye özgü diğer özellikleri de kullanmak istediğimizde utility function’lar yetersiz kalmaktadırlar.

## Renderless Components

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njmps1drq1meapc1tabf.png)

Renderless Componenet’ler herhangi bir html render etmeyen ve vue’ye özgü özellikleri kullanabildiğimiz bir yöntemdir. Burada reaktif değişkenleri veya mounted, unmounted gibi Vue’ye özgü özellikleri kullanabiliriz.

Yukarıdaki görselde yer alan örneğe baktığımızda mouse’un x ve y koordinatlarını bize anlık gösteren bir kodun renderless component ile yazıldığı örneği görüyoruz. Burada vue’ye özgü özellikleri kullanabildiğimizi görebiliriz.

## Mixins

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qw91hgf6hfmgf67l21oq.png)

Karmaşık kod bloklarını kapsüllemek için kullanabileceğimiz bir diğer yöntem de mixin’lerdir. Özellikle Options API ile geliştirme yaparken component’ler arası kod paylaşmanın resmi bir yoluydu diyebiliriz. Mixin’ler sayesinde business logic’lerimizi kapsülleyip projemizde birden fazla yerde kullanabiliyoruz.

Yukarıdaki görselde yer alan kod örneğine bakarak mixin’lerin kullanımı hakkında bilgi sahibi olabiliriz. Örneğe baktığımızda mixin’lerin içinde vue’ye özgü özellikleri kullanabildiğimizi görebiliriz.

Mixin’ler çok güzel bir çözüm gibi dursalar da çok ciddi dezavantajları olabiliyor. Bu dezavantajlarından dolayı bugün mixin’lerin kullanımı önerilmemektedir. Şimdi beraber bu dezavantajlarına bakalım.

Bu dezavantajlarından biri, bir component’te birden fazla mixin kullandığımızda hangi özelliğin hangi mixin’den geldiğini ilk bakışta anlayamıyoruz.

Diğer bir dezavantaj ise farklı mixin’lerde aynı isme sahip reaktif değişkenlerin veya method’ların yer almasıdır. Aynı reaktif değişken veya method’lar barındıran mixin’leri aynı component’te kullandığımızda conflict’ler oluşacak ve kod hatalı çalışacaktır.

Vue 3 ile birlikte mixin’ler kullanılabilirler fakat kullanılmaları önerilmemektedir. Vue özelliklerini barındıran bir kod bloğunu kapsüllemenin artık çok daha iyi bir yolu var. Şimdi hep beraber bunu inceleyelim.

## Composables

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb7o8nuzi56t76ug3b9i.png)

Composition API’nin en önemli özelliği composable’lardır. Composable’larla birlikte içinde reaktivite barındıran kod bloklarını yeniden kullanılabilir modüller haline getirebiliyoruz. Bu şekilde yazmış olduğumuz bir kodu birden fazla yerde rahatlıkla kullanabiliyoruz. Bununla beraber sadece global kod blokları oluşturmak için değil aynı zamanda bir component’te yer alan birden fazla logic’i ayırmamıza ve kodun daha okunaklı olmasına da yarıyor. Örneklerle beraber ilerleyerek composable’ları inceleyelim.

Örneğin mouse’un anlık koordinat bilgilerini veren bir kod yazmak istediğimizi düşünelim. Bunu renderless component’ler ile nasıl yapabileceğimizi görmüştük, şimdi de bunu Composition API ile nasıl yapabileceğimizi aşağıdaki görsele bakarak anlayabiliriz.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikn1yo6wly51462f9w48.png)

Yukarıda Composition API ile geliştirilen kodu projede birden çok yerde kullanmak istediğimizi düşünelim. Burada kullanabileceğimiz yöntem composable’lardır. Yukarıdaki kodu composable function haline getirdiğimizde kodumuz aşağıdaki gibi olacaktır. Aşağıdaki örneğe baktığımızda kodumuzu direkt kopyala yapıştır yaparak composable function haline getirebildiğimizi görebiliriz. Composition API’nin en büyük avantajlarından biri de kodumuzu neredeyse hiç değişiklik yapmadan başka bir yere kolaylıkla taşıyabilmemizdir.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vqxuqiozo83u1lmezvy.png)

Yukarıda yazmış olduğumuz useMouse composable function’ı herhangi bir component’te kullanmak oldukça basittir. Yapmamız gereken tek şey import etmek ve kullanmaya başlamaktır. Aşağıdaki görselde bir composable function’ın ne kadar kolay bir şekilde kullanılabildiğini görebilirsiniz.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ls5gtvawdsc4jcxpvs72.png)

## Composables vs Mixins
Composable function’larla ilgili örneklere baktığımızda mixin’lerde yaşadığımız dezavantajların yaşanmadığını görebiliriz.

- Örneğin birden fazla mixin kullandığımızda hangi özelliğin hangi mixin’den geldiğini ilk bakışta anlamak zor oluyordu fakat Composable’larda özellikle refs + destructure modelini kullandığımızda hangi özelliğin hangi composable’dan geldiğini rahatlıkla anlayabiliyoruz.

- Mixin’lerin diğer bi dezavantajı ise Namespace collisions(aynı isme sahip değişken veya method’ların vb olması) olayıdır. Composable’larda destructure ile yeniden adlandırmayla namespace collision’ların önüne geçebiliriz.

- Diğer bir avantaj ise Composable’dan döndürülen değerler, tıpkı normal fonksiyonlar gibi bir diğerine bağımsız değişkenler olarak iletilebilir.

Composable’ları iç içe de kullanabiliriz. Bu şekilde küçük logic’leri birleştirerek daha büyük logic’ler oluşturabiliriz. Bu durum web uygulaması geliştirirken component’leri kullanmamıza benziyor. Bir web uygulaması geliştirirken küçük component’leri birleştirerek daha büyük component’ler oluşturuyoruz. Bu şekilde de büyük web uygulamalarını kendimizi tekrar etmeden geliştirebiliyoruz. Bunun aynısını logic’lerimiz için de yapabiliriz. Bu durum hem kendimizi tekrar eden işlerden uzak durmamıza hem de zamandan tasarruf etmemize olanak tanıyacaktır.

Aşağıdaki örneğe baktığımızda composable’ları iç içe nasıl kullanabileceğimizi görebiliriz.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1qbg65d2hnhoswkgutmd.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/seove523zk1tzmdli3jz.png)

Örneğe baktığımızda event listener için ayrı bir composable oluşturduğumuzu ve bunu başka bir composable içinde kullanabildiğimizi görebiliriz.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9txf6v0ldpbwb5823k1b.png)

Composition API ile geliştirme yaparken kodlarımızı logic’lere göre ayırabildiğimizden bahsetmiştik. Örneğin bir composable function yazmak istediğimizi düşünelim. Yazacağımız bu function’ın da kendi içinde belli bi düzeni olması kodun okunurluğunu arttıracaktır. Üstteki örneğe baktığımızda kodda değişkenlerin bir blok halinde tanımlandığını ve fonksiyonların da ayrı bir blok halinde yazıldığını görebilirsiniz. Vue’ye özgü(computed, wathers vb.) özelliklerin de aynı şekilde ayrı bloklar halinde belli bir sıraya göre yazılması kodun okunurluğu arttıracaktır. Yukarıdaki görselde alt taraftaki kod örneğinde de olduğu gibi bu blokları yorum satırlarıyla ayırabiliriz.

## Daha İyi Ve Sürdürülebilir Composable’lar Yazmak

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxp4fmtuaowqi5f1ncsd.png)

Composition API ve Composable’larla ilgili kod örneklerine beraber baktık. Composable’ların kodumuzda yer alan logic’leri tekrar tekrar kullanabileceğimiz fonksiyonlara ayırmamıza izin verdiklerini gördük. Bunun da kodun yazılmasını ve okunmasını kolaylaştırdığından bahsettik.

Şimdi de beraber composable’larımızı daha iyi nasıl yazabileceğimize bakalım. Bu konuyla ilgili hazırlık yaparken incelediğim birçok kaynak oldu fakat bu kaynaklar arasında özellikle Michael Thiessen’ın yazmış olduğu “Coding Better Composables” yazısı çok ilgimi çekti. Konuyu ele alış biçimi ve yalın örnekleriyle konuyu çok güzel özetlemiş. Yazı dizisini incelemenizi kesinlikle tavsiye ederim. Bahsettiğim yazıda bu konu çok iyi anlatıldığından oradaki örneklerle konuyu anlatmak istiyorum. Bu yazıda çok detaya girmeden ilerleyeceğimizden dolayı detaylı bilgi almak için ilgili yazıyı incelemenizi tekrardan tavsiye ediyorum.

Konu hakkında bilgi verirken yine kod örnekleriyle ilerleyeceğiz. Bu sefer kod örnekleri için VueUse kütüphanesinden yararlanacağız. VueUse kütüphanesi, içinde hazır composable’lar olan ve open source olan bir kütüphanedir. Bu kütüphanede composable’lar nasıl yazılmış bunlara beraber bakacağız. Bu şekilde de kendi composable’larımızı yazarken nelere dikkat etmemiz gerektiğini de anlamış olacağız.

## Parametreleri Obje Olarak Geçmek

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mmgw8svpmue3xvjslb5.png)

Composable’ların çoğunda bir veya daha fazla parametre bulunabilir. Fonksiyonumuza fazla sayıda parametre geçmek yerine hepsini tek bir obje olarak geçebiliriz. Fonksiyon içinde de object destructure ile ilerleyerek devam edebiliriz. Bir veya iki parametre dışında kalan parametreleri obje olarak geçmek bizim için avantajlı olacaktır.

Birincisi parametrelerin sırasını bilmemiz gerekmiyor. Parametleri obje olarak geçtiğimiz sürece sıralamanın bir önemi yoktur. Bu sayede olası hataların önüne geçebiliriz.

İkincisi ise obje olarak geçtiğimiz parametlerin ne işe yaradığını property’lerin isimlendirmelerinden anlayabiliriz. Bu da kodumuzu daha okunur yapacaktır.

Şimdi de bu konu ile ilgili bir örneğe beraber bakalım. VueUse kütüphanesinde olan useTitle composable’ında bu işlemin nasıl yapıldığını görebiliriz. useTitle composable’ı oldukça basittir. Sayfanın başlığını ayarlamamızı sağlar.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kecs8a1ihnwdh1pcma76.png)

Buradaki örneğe baktığımızda title parametresi dışında kalan diğer parametreler options nesnesi olarak alınmıştır. Bizde yazdığımız composable’larda bu şekilde ilerleyebiliriz.

## Parametrelerin Esnek Olması (Reaktif Veya Primitive Türlerin Otomatik Ayarlanması)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sljhwad5t92e9h47wxrg.png)

Composable’ların parametre alabileceğinden bahsetmiştik. Bu parametreler ilkel javascript türleri (string, number) olabileceği gibi reaktif değişkenler de olabilir. Bazı durumlarda parametrenin ne olursa olsun reaktif bir değişken olmasını veya ne olursa olsun ilkel bir tip olmasını isteyebiliriz. Burada parametre olarak özellikle reaktif bir değişken veya ilkel bir tür istemek yerine ikisini de kabul edip ardından bu parametreyi ihtiyacımız olan türe dönüştürebiliriz.

Yukarıdaki örneğe baktığımızda bu işlemin “ref” ve “unref” ile çok kolay bir şekilde yapılabileceğini görebiliriz. Bu sayede girilen parametrenin türü ne olursa olsun onu istediğimiz türe(reaktif veya primitive) dönüştürüp devam edebiliriz. Bu şekilde olası hataların önüne rahatlıkla geçebiliriz.

Şimdi de bu işlemin yine UseTitle örneğinden ilerleyerek nasıl yapılabileceğini görelim.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9igjsjcq2zbuopsgtgrz.png)

Yukarıdaki koda baktığımızda girilen parametre ne olursa olsun reaktif hale getirildiğini görebiliriz.

## Dinamik Dönüş Değerleri
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eno6ba7d3126yl2axk5u.png)

Composable’lar tek bir değer döndürebileceği gibi içinde birden fazla değer barındıran bir obje de döndürebilir. Yukarıdaki örnekte her iki örneği de görebilirsiniz. useDark tek bir değer dönerken useMouse bir obje dönmektedir. Burada istersek yazacağımız composable’ın değerlerini dinamik yapabiliriz. Dışarıdan girilen parametreye göre tek bir değer veya obje döndürebiliriz. Bu işlemi basit bir kontrol ile çok kolay bir şekilde gerçekleştirebiliriz. Yukarıdaki örnekte “controls: true” girildiğinde obje dönmektedir aksi takdirde tek bir değer dönmektedir.

Bu kalıp çoğu zaman kodumuzu basitlemştirmek için iyi bir yöntemdir. Şimdi de bu işlemin VueUse kütüphanesinde UseNow composable’ında nasıl yapıldığına bakalım.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnbr1i6mcsmpenax1a5f.png)

Yukarıdaki örneğe baktığımızda bu işlemin basit bir if kontrolü ile yapıldığını görebiliriz.

## Composable ile Kodun Düzenlenmesi

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2js15y1q05scfm90phd.png)

Composable’ları sadece global kod blokları oluşturmak için değil aynı zamanda kod organizasyonu için de kullanabiliriz. Örneğin bir component’te logic’ler arttıkça kodu okumak ve anlamak daha zor hale gelebilir. Bu tarz durumlar için her bir logic için ayrı bi composable oluşturup kodumuzu küçük parçalara ayırabiliriz. Ayrıca bir composable’dan aldığımız değişkeni başka bi composable’a parametre olarak geçebiliriz. Bu da kod organizasyonu için önemli bi avantaj sağlayacaktır.

## Özet Ve Teşekkür

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1uc0on2i6wapj054o31.png)

Bu yazımda sizlere öncelikle Composition API öncesinde ne gibi zorluklar yaşadığımızdan örneklerle birlikte bahsettim. Bu örneklerle birlikte neden Composition API’ya ihtiyaç duyduğumuzu ve Composition API ile bu sorunların nasıl aşıldığını yine örneklerle beraber görmüş olduk. Sonrasında ise Michael Thiessen’ın yazmış olduğu “Coding Better Composables” yazısından örneklerle giderek Composable’larımızı daha iyi nasıl yazabileceğimizi yine örneklerle beraber inceledik.

Dilerseniz bu yazının sunumunu aşağıdan izleyebilirsiniz.

https://youtu.be/bfIDcdHbIbI

Burada anlatılanların işinize yaraması dileğiyle :)

## Kaynaklar
- https://vuejs.org/guide/reusability/composables.html#what-is-a-composable

- https://medium.com/vue-mastery/coding-better-composables-1-5-47c6f17d1cd3

- https://vuejs.org/guide/reusability/composables.html#mouse-tracker-example

- 
https://vuejs.org/guide/reusability/composables.html#conventions-and-best-practices

- https://medium.com/vue-mastery/coding-better-composables-flexible-arguments-2-5-6eff5983bb1

- https://vuejs.org/guide/reusability/composables.html#extracting-composables-for-code-organization

- https://vuejs.org/guide/reusability/composables.html#comparisons-with-other-techniques

- https://medium.com/vue-mastery/coding-better-composables-dynamic-returns-3-5-3542702dd618

- https://vuejs.org/guide/components/slots.html#scoped-slots
https://dev.to/the_one/are-you-using-composition-api-the-right-way-4jmm

- https://www.sitepoint.com/vue-composition-api-reusable-components/

- https://vuejs.org/guide/scaling-up/sfc.html

- https://en.wikipedia.org/wiki/Don%27t_repeat_yourself