paint-brush
Vue.js ile İstemciyi Geliştirmeile@nfrankel
260 okumalar

Vue.js ile İstemciyi Geliştirme

ile Nicolas Fränkel17m2024/09/26
Read on Terminal Reader

Çok uzun; Okumak

Bu gönderide, Vue ile bir SSR uygulamasını zenginleştirmeye yönelik ilk adımlarımı attım. Oldukça basitti. Karşılaştığım en büyük sorun, Vue'nin satır şablonunu değiştirmesiydi: Belgeleri kapsamlı bir şekilde okumadım ve is niteliğini kaçırdım.
featured image - Vue.js ile İstemciyi Geliştirme
Nicolas Fränkel HackerNoon profile picture
0-item


Önceki yazımda üzerine inşa edeceğimiz temelleri atmıştım; şimdi "gerçekten" başlamanın zamanı.


Vue.js hakkında çok şey duydum. Ayrıca, geliştiriciden yöneticiliğe geçen bir arkadaşım bana Vue hakkında güzel şeyler söyledi, bu da ilgimi daha da çekti. Bir göz atmaya karar verdim: Bu, bir acemi olarak, ki ben de öyleyim, inceleyeceğim ilk "hafif" JavaScript framework'ü olacak.

Çalışmanın düzenlenmesi

WebJars ve Thymeleaf'ı son yazımda açıklamıştım. İşte kurulum, sunucu ve istemci tarafı.

Sunucu tarafı

İşte ikisini de POM'a nasıl entegre ettiğim:


 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <!--1--> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <!--2--> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <!--3--> <version>0.52</version> </dependency> <dependency> <groupId>org.webjars.npm</groupId> <artifactId>vue</artifactId> <!--4--> <version>3.4.34</version> </dependency> </dependencies>
  1. Spring Boot'un kendisi; düzenli, tepkisiz yaklaşımı seçtim
  2. Spring Boot Thymeleaf entegrasyonu
  3. İstemci tarafında Vue sürümünü belirtmekten kaçınmak için WebJars konum belirleyicisi
  4. Vue, sonunda!


Spring Boot tarafında Kotlin Router ve Bean DSL'leri kullanıyorum:


 fun vue(todos: List<Todo>) = router { //1 GET("/vue") { ok().render("vue", mapOf("title" to "Vue.js", "todos" to todos)) //2-3 } }
  1. Statik bir Todo nesneleri listesi geçirin
  2. Aşağıya bakın
  3. Modeli Thymeleaf'e iletin


API geliştirmeye alışkınsanız, body() fonksiyonuna aşinasınızdır; bu fonksiyon, yükü doğrudan, muhtemelen JSON formatında döndürür. render() akışı görünüm teknolojisine, bu durumda Thymeleaf'e iletir. İki parametre kabul eder:


  1. Görünümün adı. Varsayılan olarak, yol /templates ve önek .html ; bu durumda, Thymeleaf /templates/vue.html bir görünüm bekler
  2. Anahtar-değer çiftlerinin bir model haritası

İstemci tarafı

İşte HTML tarafındaki kod:


 <script th:src="@{/webjars/axios/dist/axios.js}" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js"></script> <!--1--> <script th:src="@{/webjars/vue/dist/vue.global.js}" src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script> <!--2--> <script th:src="@{/vue.js}" src="../static/vue.js"></script> <!--3--> <script th:inline="javascript"> /*<![CDATA[*/ window.vueData = { <!--4--> title: /*[[${ title }]]*/ 'A Title', todos: /*[[${ todos }]]*/ [{ 'id': 1, 'label': 'Take out the trash', 'completed': false }] }; /*]]>*/ </script>
  1. Axios HTTP isteklerinin yapılmasına yardımcı olur
  2. Vue'nin kendisi
  3. İstemci tarafındaki kodumuz
  4. Verileri ayarlayın


Geçtiğimiz haftaki makalede açıklandığı gibi, Thymeleaf'in avantajlarından biri hem statik dosya işleme hem de sunucu tarafı işleme izin vermesidir. Sihrin işe yaraması için, bir istemci tarafı yolu, yani src ve bir sunucu tarafı yolu, yani th:src belirtiyorum.


Vue kodu

Şimdi Vue kodlarına dalalım.

Birkaç özelliği hayata geçirmek istiyoruz:


  1. Sayfa yüklendikten sonra, sayfa tüm Todo öğelerini görüntülemelidir
  2. Bir Todo tamamlandı onay kutusuna tıklandığında, completed niteliği ayarlanmalı/ayarlanmamalıdır
  3. Temizleme düğmesine tıklandığında, tamamlanmış tüm Todo silinir
  4. Ekle butonuna tıklandığında, Todo listesine aşağıdaki değerlere sahip bir Todo eklenmelidir:
    • id : Sunucu tarafında hesaplanan, diğer tüm ID'lerin maksimum değeri artı 1
    • label : label için Etiket alanının değeri
    • completed : false olarak ayarlandı

Vue'ye ilk adımlarımız

İlk adım framework'ü başlatmaktır. Yukarıda özel vue.js dosyamız için referansı zaten ayarladık.


 document.addEventListener('DOMContentLoaded', () => { //1 // The next JavaScript code snippets will be inside the block }
  1. DOM yüklemeyi tamamladığında bloğu çalıştırın


Bir sonraki adım Vue'nun sayfanın bir kısmını yönetmesine izin vermektir. HTML tarafında, Vue'nun hangi üst düzey kısmı yöneteceğine karar vermeliyiz. İsteğe bağlı bir <div> seçebilir ve gerekirse daha sonra değiştirebiliriz.


 <div id="app"> </div>


JavaScript tarafında, önceki HTML <div> seçicisini CSS seçicisine geçirerek bir uygulama oluşturuyoruz.


 Vue.createApp({}).mount('#app');


Bu noktada sayfa yüklendiğinde Vue'yu başlatıyoruz ancak görünürde hiçbir şey olmuyor.


Bir sonraki adım bir Vue şablonu oluşturmaktır. Bir Vue şablonu, Vue tarafından yönetilen normal bir HTML <template> udur. Vue'yi Javascript'te tanımlayabilirsiniz, ancak bunu HTML sayfasında yapmayı tercih ediyorum.


Başlığı görüntüleyebilecek bir kök şablonla başlayalım.


 <template id="todos-app"> <!--1--> <h1>{{ title }}</h1> <!--2--> </template>
  1. Kolay bağlama için kimliği ayarlayın
  2. title özelliğini kullanın; kurulumu yapılması gerekiyor


JavaScript tarafında ise yönetim kodunu oluşturmamız gerekiyor.


 const TodosApp = { props: ['title'], //1 template: document.getElementById('todos-app').innerHTML, }
  1. HTML şablonunda kullanılan title özelliğini bildirin


Son olarak, uygulamayı oluştururken şu nesneyi iletmemiz gerekiyor:


 Vue.createApp({ components: { TodosApp }, //1 render() { //2 return Vue.h(TodosApp, { //3 title: window.vueData.title, //4 }) } }).mount('#app');
  1. Bileşeni yapılandırın
  2. Vue, render() fonksiyonunu bekliyor
  3. hipermetin için h() nesneden ve onun özelliklerinden sanal bir düğüm oluşturur
  4. title özelliğini sunucu tarafında oluşturulan değerle başlatın


Bu noktada Vue başlığı görüntüler.

Temel etkileşimler

Bu noktada, kullanıcı bir onay kutusuna tıkladığında eylemi uygulayabiliriz: sunucu tarafındaki durumda güncellenmesi gerekir.

Öncelikle, Todo görüntüleyen tablo için yeni bir iç içe geçmiş Vue şablonu ekledim. Yazıyı uzatmamak için, ayrıntılı olarak açıklamaktan kaçınacağım. İlginizi çekerse, kaynak koduna bir göz atın.


Başlangıç satırı şablonunun kodu sırasıyla JavaScript ve HTML olarak şöyledir:


 const TodoLine = { props: ['todo'], template: document.getElementById('todo-line').innerHTML }
 <template id="todo-line"> <tr> <td>{{ todo.id }}</td> <!--1--> <td>{{ todo.label }}</td> <!--2--> <td> <label> <input type="checkbox" :checked="todo.completed" /> </label> </td> </tr> </template>
  1. Todo kimliğini göster
  2. Todo etiketini görüntüle
  3. completed niteliği true kutuyu işaretleyin


Vue, @ sözdizimi aracılığıyla olay işleme olanağı sağlar.


 <input type="checkbox" :checked="todo.completed" @click="check" />


Kullanıcı satıra tıkladığında Vue şablonun check() fonksiyonunu çağırır. Bu fonksiyonu bir setup() parametresinde tanımlarız:


 const TodoLine = { props: ['todo'], template: document.getElementById('todo-line').innerHTML, setup(props) { //1 const check = function (event) { //2 const { todo } = props axios.patch( //3 `/api/todo/${todo.id}`, //4 { checked: event.target.checked } //5 ) } return { check } //6 } }
  1. props dizisini kabul edin, böylece daha sonra erişebiliriz
  2. Vue, çağrıyı tetikleyen event geçirir
  3. Axios, HTTP çağrılarını basitleştiren bir JavaScript kütüphanesidir
  4. Sunucu tarafının bir API sağlaması gerekir ; bu yazının kapsamı dışındadır, ancak kaynak kodlarını kontrol etmekten çekinmeyin.
  5. JSON yükü
  6. Tanımlanmış tüm fonksiyonları HTML'den erişilebilir kılmak için geri döndürüyoruz

İstemci tarafı modeli

Önceki bölümde iki hata yaptım:


  • Hiçbir yerel modeli yönetemedim
  • HTTP yanıtının çağrı yöntemini kullanmadım


Bunu, tamamlanan görevlerin temizlenmesi olan bir sonraki özelliği uygulayarak yapacağız.


Artık Vue üzerinden olayların nasıl işleneceğini biliyoruz:


 <button class="btn btn-warning" @click="cleanup">Cleanup</button>


TodosApp nesnesine aynı isimli bir fonksiyon ekliyoruz:


 const TodosApp = { props: ['title', 'todos'], components: { TodoLine }, template: document.getElementById('todos-app').innerHTML, setup() { const cleanup = function() { //1 axios.delete('/api/todo:cleanup').then(response => { //1 state.value.todos = response.data //2-3 }) } return { cleanup } //1 } }
  1. Yukarıdaki gibi
  2. Axios, HTTP çağrısının otomatik JSON dönüşümünü sunar
  3. state modeli depoladığımız yerdir


Vue'nun semantiğinde, Vue modeli reaktif olmasını istediğimiz verilerin etrafında bir sarmalayıcıdır. Reaktif, görünüm ve model arasında iki yönlü bağlama anlamına gelir. Mevcut bir değeri ref() metoduna geçirerek reaktif hale getirebiliriz:


Composition API'sinde reaktif durumu bildirmenin önerilen yolu ref() fonksiyonunu kullanmaktır.


ref() argümanı alır ve onu .value özelliğine sahip bir ref nesnesi içinde sarılı olarak döndürür.


Bir bileşenin şablonundaki referanslara erişmek için, bunları bileşenin setup() fonksiyonundan bildirin ve döndürün.


-- Reaktif Durumun Bildirilmesi


Hadi yapalım:


 const state = ref({ title: window.vueData.title, //1-2 todos: window.vueData.todos, //1 }) createApp({ components: { TodosApp }, setup() { return { ...state.value } //3-4 }, render() { return h(TodosApp, { todos: state.value.todos, //5 title: state.value.title, //5 }) } }).mount('#app');
  1. Yukarıda açıklandığı gibi, Thymeleaf aracılığıyla HTML sayfasındaki veri kümesini alın
  2. title ayarlama şeklimizi değiştiriyoruz. İki yönlü bir bağlama olmadığı için bu gerekli değil - başlığı istemci tarafında güncellemiyoruz, ancak tüm değerler arasında işlemeyi tutarlı tutmayı tercih ediyorum
  3. Vue'nun beklentileri doğrultusunda referansları geri döndürün
  4. Bakın anne, JavaScript spread operatörünü kullanıyorum
  5. Nesnenin özniteliğini state yapılandırın


Bu noktada reaktif bir istemci tarafı modelimiz var.


HTML tarafında ilgili Vue niteliklerini kullanıyoruz:


 <tbody> <tr is="vue:todo-line" v-for="todo in todos" :key="todo.id" :todo="todo"></tr> <!--1-2--> </tbody>
  1. Todo nesnelerinin listesi üzerinde döngü
  2. is niteliği, tarayıcının HTML'yi ayrıştırma biçimiyle başa çıkmak için çok önemlidir. Daha fazla ayrıntı için Vue belgelerine bakın

Yukarıda ilgili şablonu anlattım.

Modelin güncellenmesi

Artık yeni bir özellik uygulayabiliriz: istemciden yeni bir Todo ekleyin. Ekle düğmesine tıkladığımızda, Etiket alan değerini okuruz, verileri API'ye göndeririz ve modeli yanıtla yenileriz.


İşte güncellenmiş kod:


 const TodosApp = { props: ['title', 'todos'], components: { TodoLine }, template: document.getElementById('todos-app').innerHTML, setup() { const label = ref('') //1 const create = function() { //2 axios.post('/api/todo', { label: label.value }).then(response => { state.value.todos.push(response.data) //3 }).then(() => { label.value = '' //4 }) } const cleanup = function() { axios.delete('/api/todo:cleanup').then(response => { state.value.todos = response.data //5 }) } return { label, create, cleanup } } }
  1. Kapsamı işlevle sınırlı olan başlığın etrafında reaktif bir sarmalayıcı oluşturun
  2. create() fonksiyonu uygun
  3. API çağrısı tarafından döndürülen yeni JSON nesnesini Todo listesine ekleyin
  4. Alanın değerini sıfırla
  5. Silerken tüm listeyi değiştirin; mekanizma aynıdır


HTML tarafında bir buton ekliyoruz ve create() fonksiyonuna bağlıyoruz. Aynı şekilde Label alanını da ekliyoruz ve onu modele bağlıyoruz.


 <form> <div class="form-group row"> <label for="new-todo-label" class="col-auto col-form-label">New task</label> <div class="col-10"> <input type="text" id="new-todo-label" placeholder="Label" class="form-control" v-model="label" /> </div> <div class="col-auto"> <button type="button" class="btn btn-success" @click="create">Add</button> </div> </div> </form>


Vue, create() fonksiyonunu HTML düğmesine bağlar. Bunu eş zamanlı olarak çağırır ve çağrı tarafından döndürülen yeni öğeyle reaktif Todo listesini yeniler. Aynısını, işaretli Todo nesnelerini kaldırmak için Cleanup düğmesi için de yaparız.


Kodu gereğinden fazla karmaşık hale getirmekten kaçınmak için bilerek herhangi bir hata işleme kodu uygulamadığımı unutmayın. İlk deneyim için yeterli içgörü elde ettiğimizden burada duracağım.

Çözüm

Bu gönderide, Vue ile bir SSR uygulamasını zenginleştirmeye yönelik ilk adımlarımı attım. Oldukça basitti. Karşılaştığım en büyük sorun, Vue'nin satır şablonunu değiştirmesiydi: Belgeleri kapsamlı bir şekilde okumadım ve is niteliğini kaçırdım.


Ancak HTTP çağrılarında Axios'u kullanmama rağmen bir hayli satır JavaScript yazmam gerekti ve hataları yönetemedim.


Bir sonraki yazımda aynı özellikleri Alpine.js ile uygulayacağım.


Bu yazının tam kaynak koduna GitHub'dan ulaşabilirsiniz:

Daha ileri gidelim: