paint-brush
Menambah Pelanggan Dengan Vue.jsoleh@nfrankel
sejarah baru

Menambah Pelanggan Dengan Vue.js

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

Terlalu panjang; Untuk membaca

Dalam siaran ini, saya mengambil langkah pertama saya dalam menambah apl SSR dengan Vue. Ia agak mudah. Isu terbesar yang saya temui ialah untuk Vue menggantikan templat baris: Saya tidak membaca dokumentasi secara meluas dan terlepas atribut is.
featured image - Menambah Pelanggan Dengan Vue.js
Nicolas Fränkel HackerNoon profile picture
0-item


Dalam catatan saya sebelum ini , saya meletakkan asas untuk membina; sekarang adalah masa untuk memulakan "sebenarnya".


Saya mendengar banyak Vue.js . Selain itu, rakan yang beralih daripada pembangun kepada pengurus memberitahu saya perkara yang baik tentang Vue, yang seterusnya menarik minat saya. Saya memutuskan untuk melihatnya: ia akan menjadi rangka kerja JavaScript "ringan" pertama yang akan saya kaji - dari sudut pandangan seorang pemula, iaitu saya.

Meletakkan kerja

Saya menerangkan WebJars dan Thymeleaf dalam jawatan terakhir. Berikut ialah persediaan, bahagian pelayan dan pelanggan.

Bahagian pelayan

Inilah cara saya mengintegrasikan kedua-duanya dalam POM:


 <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 itu sendiri; Saya memutuskan pendekatan biasa, tidak reaktif
  2. Penyepaduan Spring Boot Thymeleaf
  3. WebJars locator, untuk mengelak daripada menentukan versi Vue pada bahagian klien
  4. Vue, akhirnya!


Saya menggunakan Penghala Kotlin dan DSL Bean pada bahagian Spring Boot:


 fun vue(todos: List<Todo>) = router { //1 GET("/vue") { ok().render("vue", mapOf("title" to "Vue.js", "todos" to todos)) //2-3 } }
  1. Lulus senarai statik objek Todo
  2. Lihat di bawah
  3. Hantar model kepada Thymeleaf


Jika anda biasa membangunkan API, anda sudah biasa dengan fungsi body() ; ia mengembalikan muatan secara langsung, mungkin dalam format JSON. render() menghantar aliran ke teknologi paparan, dalam kes ini, Thymeleaf. Ia menerima dua parameter:


  1. Nama pandangan. Secara lalai, laluannya ialah /templates dan awalan ialah .html ; dalam kes ini, Thymeleaf menjangkakan paparan di /templates/vue.html
  2. Peta model pasangan nilai kunci

Pihak pelanggan

Berikut ialah kod di sebelah HTML:


 <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 membantu membuat permintaan HTTP
  2. Vue sendiri
  3. Kod pihak pelanggan kami
  4. Tetapkan data


Seperti yang dijelaskan dalam artikel minggu lepas, salah satu faedah Thymeleaf ialah ia membenarkan pemaparan fail statik dan pemaparan sebelah pelayan. Untuk membuat keajaiban berfungsi, saya menentukan laluan sisi klien, iaitu , src dan laluan sisi pelayan, iaitu , th:src .


Kod Vue

Sekarang, mari kita selami kod Vue.

Kami ingin melaksanakan beberapa ciri:


  1. Selepas halaman dimuatkan, halaman harus memaparkan semua item Todo
  2. Apabila mengklik pada kotak semak Todo complete, ia harus menetapkan/menyahset atribut completed
  3. Apabila mengklik pada butang Pembersihan , ia memadam semua Todo yang telah selesai
  4. Apabila mengklik pada butang Tambah , ia harus menambah Todo ke senarai Todo dengan nilai berikut:
    • id : ID pengiraan sebelah pelayan sebagai maksimum semua ID lain tambah 1
    • label : nilai medan Label untuk label
    • completed : ditetapkan kepada false

Langkah pertama kami ke Vue

Langkah pertama ialah bootstrap rangka kerja. Kami telah menyediakan rujukan untuk fail vue.js tersuai kami di atas.


 document.addEventListener('DOMContentLoaded', () => { //1 // The next JavaScript code snippets will be inside the block }
  1. Jalankan blok apabila DOM telah selesai dimuatkan


Langkah seterusnya ialah membenarkan Vue mengurus sebahagian halaman. Dari segi HTML, kita mesti memutuskan bahagian peringkat teratas yang Vue uruskan. Kita boleh memilih <div> sewenang-wenangnya dan mengubahnya kemudian jika perlu.


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


Di sisi JavaScript, kami mencipta apl , melepasi pemilih CSS bagi HTML sebelumnya <div> .


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


Pada ketika ini, kami melancarkan Vue apabila halaman dimuatkan, tetapi tiada apa yang kelihatan berlaku.


Langkah seterusnya ialah membuat templat Vue . Templat Vue ialah <template> HTML biasa yang diuruskan oleh Vue. Anda boleh menentukan Vue dalam Javascript, tetapi saya lebih suka melakukannya pada halaman HTML.


Mari kita mulakan dengan templat akar yang boleh memaparkan tajuk.


 <template id="todos-app"> <!--1--> <h1>{{ title }}</h1> <!--2--> </template>
  1. Tetapkan ID agar mudah diikat
  2. Gunakan harta title ; ia masih perlu disediakan


Di sisi JavaScript, kita mesti mencipta kod pengurusan.


 const TodosApp = { props: ['title'], //1 template: document.getElementById('todos-app').innerHTML, }
  1. Isytiharkan harta title , yang digunakan dalam templat HTML


Akhir sekali, kita mesti lulus objek ini apabila kita mencipta aplikasi:


 Vue.createApp({ components: { TodosApp }, //1 render() { //2 return Vue.h(TodosApp, { //3 title: window.vueData.title, //4 }) } }).mount('#app');
  1. Konfigurasikan komponen
  2. Vue menjangkakan fungsi render()
  3. h() untuk hiperskrip mencipta nod maya daripada objek dan sifatnya
  4. Mulakan sifat title dengan bahagian pelayan yang dijana nilai


Pada ketika ini, Vue memaparkan tajuk.

Interaksi asas

Pada ketika ini, kami boleh melaksanakan tindakan apabila pengguna mengklik pada kotak pilihan: ia perlu dikemas kini dalam keadaan sebelah pelayan.

Mula-mula, saya menambah templat Vue bersarang baharu untuk jadual yang memaparkan Todo . Untuk mengelak daripada memanjangkan siaran, saya akan mengelak daripada menerangkannya secara terperinci. Jika anda berminat, sila lihat kod sumber .


Berikut ialah kod templat baris permulaan, masing-masing JavaScript dan HTML:


 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. Paparkan id Todo
  2. Paparkan label Todo
  3. Tandai kotak jika atribut completed adalah true


Vue membenarkan pengendalian acara melalui sintaks @ .


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


Vue memanggil fungsi check() templat apabila pengguna mengklik pada baris. Kami mentakrifkan fungsi ini dalam parameter setup() :


 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. Terima tatasusunan props , supaya kami boleh mengaksesnya kemudian
  2. Vue melepasi event yang mencetuskan panggilan
  3. Axios ialah lib JavaScript yang memudahkan panggilan HTTP
  4. Bahagian pelayan mesti menyediakan API; ia di luar skop siaran ini, tetapi jangan ragu untuk menyemak kod sumber.
  5. Muatan JSON
  6. Kami mengembalikan semua fungsi yang ditentukan untuk menjadikannya boleh diakses daripada HTML

Model sisi pelanggan

Dalam bahagian sebelumnya, saya membuat dua kesilapan:


  • Saya tidak menguruskan mana-mana model tempatan
  • Saya tidak menggunakan kaedah panggilan respons HTTP


Kami akan melakukannya dengan melaksanakan ciri seterusnya, iaitu pembersihan tugasan yang telah selesai.


Kami kini tahu cara mengendalikan acara melalui Vue:


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


Pada objek TodosApp , kami menambah fungsi dengan nama yang sama:


 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. Seperti di atas
  2. Axios menawarkan penukaran JSON automatik bagi panggilan HTTP
  3. state adalah tempat kami menyimpan model


Dalam semantik Vue, model Vue ialah pembalut di sekeliling data yang kita mahu reaktif . Reaktif bermaksud pengikatan dua hala antara pandangan dan model. Kita boleh membuat nilai sedia ada reaktif dengan menghantarnya ke kaedah ref() :


Dalam API Komposisi, cara yang disyorkan untuk mengisytiharkan keadaan reaktif adalah menggunakan fungsi ref() .


ref() mengambil hujah dan mengembalikannya dibalut dalam objek ref dengan sifat .value.


Untuk mengakses rujukan dalam templat komponen, isytiharkan dan kembalikannya daripada fungsi setup() komponen.


-- Mengisytiharkan Keadaan Reaktif


Jom buat:


 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. Dapatkan set data dalam halaman HTML, melalui Thymeleaf, seperti yang dijelaskan di atas
  2. Kami mengubah cara kami menetapkan title . Ia tidak perlu kerana tiada pengikatan dua hala - kami tidak mengemas kini tajuk bahagian klien, tetapi saya lebih suka mengekalkan pengendalian yang koheren merentas semua nilai
  3. Kembalikan rujukan, mengikut jangkaan Vue
  4. Lihat, ma, saya menggunakan operator spread JavaScript
  5. Konfigurasikan objek yang diatributkan daripada state


Pada ketika ini, kami mempunyai model sisi pelanggan yang reaktif .


Di bahagian HTML, kami menggunakan atribut Vue yang berkaitan:


 <tbody> <tr is="vue:todo-line" v-for="todo in todos" :key="todo.id" :todo="todo"></tr> <!--1-2--> </tbody>
  1. Gelung pada senarai objek Todo
  2. Atribut is adalah penting untuk mengatasi cara pelayar menghuraikan HTML. Lihat dokumentasi Vue untuk butiran lanjut

Saya telah menerangkan templat yang sepadan di atas.

Mengemas kini model

Kami kini boleh melaksanakan ciri baharu: tambah Todo baharu daripada klien. Apabila mengklik pada butang Tambah , kami membaca nilai medan Label , menghantar data ke API, dan menyegarkan model dengan respons.


Berikut ialah kod yang dikemas kini:


 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. Buat pembalut reaktif di sekeliling tajuk yang skopnya terhad kepada fungsi
  2. Fungsi create() betul
  3. Tambahkan objek JSON baharu yang dikembalikan oleh panggilan API ke senarai Todo
  4. Tetapkan semula nilai medan
  5. Gantikan keseluruhan senarai apabila memadam; mekanismenya adalah sama


Di sebelah HTML, kami menambah butang dan mengikat kepada fungsi create() . Begitu juga, kami menambah medan Label dan mengikatnya pada model.


 <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 mengikat fungsi create() pada butang HTML. Ia memanggilnya secara tidak segerak dan menyegarkan senarai Todo reaktif dengan item baharu yang dikembalikan melalui panggilan. Kami melakukan perkara yang sama untuk butang Pembersihan , untuk mengalih keluar objek Todo yang diperiksa.


Ambil perhatian bahawa saya tidak sengaja melaksanakan sebarang kod pengendalian ralat untuk mengelakkan membuat kod lebih kompleks daripada yang diperlukan. Saya akan berhenti di sini kerana kami memperoleh cukup cerapan untuk pengalaman pertama.

Kesimpulan

Dalam siaran ini, saya mengambil langkah pertama saya dalam menambah apl SSR dengan Vue. Ia agak mudah. Isu terbesar yang saya temui ialah untuk Vue menggantikan templat baris: Saya tidak membaca dokumentasi secara meluas dan terlepas atribut is .


Walau bagaimanapun, saya terpaksa menulis beberapa baris JavaScript, walaupun saya menggunakan Axios untuk membantu saya dengan panggilan HTTP dan tidak menguruskan ralat.


Dalam siaran seterusnya, saya akan melaksanakan ciri yang sama dengan Alpine.js.


Kod sumber lengkap untuk siaran ini boleh didapati di GitHub:

Pergi lebih jauh:



L O A D I N G
. . . comments & more!

About Author

Nicolas Fränkel HackerNoon profile picture
Nicolas Fränkel@nfrankel
Developer Advocate for Apache APISIX *** Learner *** Author of http://leanpub.com/integrationtest

GANTUNG TANDA

ARTIKEL INI DIBENTANGKAN DALAM...