Oldingi postimda men qurilish uchun zamin yaratdim; endi "haqiqiy" boshlash vaqti.
Men juda ko'p Vue.js eshitdim. Bundan tashqari, ishlab chiquvchidan menejerga o'tgan do'stim menga Vue haqida yaxshi narsalarni aytib berdi, bu mening qiziqishimni yanada oshirdi. Men buni ko'rib chiqishga qaror qildim: bu men o'rganadigan birinchi "engil" JavaScript ramkasi bo'ladi - men yangi boshlovchi nuqtai nazaridan.
Ishni tartibga solish
Men oxirgi postda WebJars va Thymeleafni tushuntirdim. Bu yerda sozlash, server va mijoz tomoni.
Server tomoni
Men ikkalasini ham POMga qanday qilib birlashtiraman:
<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>
- Spring Bootning o'zi; Men muntazam, noreaktiv yondashuvga qaror qildim
- Spring Boot Thymeleaf integratsiyasi
- Mijoz tomonida Vue versiyasini ko'rsatmaslik uchun WebJars lokatori
- Vue, nihoyat!
Men Spring Boot tomonida Kotlin Router va Bean DSL-dan foydalanmoqdaman:
fun vue(todos: List<Todo>) = router { //1 GET("/vue") { ok().render("vue", mapOf("title" to "Vue.js", "todos" to todos)) //2-3 } }
-
Todo
ob'ektlarining statik ro'yxatini o'tkazing - Pastga qarang
- Modelni Thymeleafga uzating
Agar siz API-larni ishlab chiqishga odatlangan bo'lsangiz, siz body()
funksiyasi bilan tanishsiz; u to'g'ridan-to'g'ri foydali yukni qaytaradi, ehtimol JSON formatida. render()
oqimni ko'rish texnologiyasiga o'tkazadi, bu holda Thymeleaf. U ikkita parametrni qabul qiladi:
- Ko'rinishning nomi. Odatiy bo'lib, yo'l
/templates
va prefiks.html
; bu holda, Thymeleaf/templates/vue.html
manzilida ko'rinishni kutadi - Kalit-qiymat juftliklarining namunaviy xaritasi
Mijoz tomoni
Mana HTML tomonidagi 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>
- Axios HTTP so'rovlarini bajarishga yordam beradi
- Vue o'zi
- Bizning mijoz kodimiz
- Ma'lumotlarni o'rnating
O'tgan haftadagi maqolada aytib o'tilganidek, Thymeleafning afzalliklaridan biri shundaki, u statik fayllarni va server tomonida ko'rsatish imkonini beradi. Sehrli ish qilish uchun men mijoz tomoni yo'lini, ya'ni src
va server tomonini, ya'ni th:src
belgilayman.
Vue kodi
Keling, Vue kodiga o'taylik.
Biz bir nechta xususiyatlarni amalga oshirishni xohlaymiz:
- Sahifani yuklagandan so'ng, sahifa barcha
Todo
elementlarini ko'rsatishi kerak -
Todo
tugallangan katakchani bosganingizda, ucompleted
atributni o'rnatishi/o'chirishi kerak - Tozalash tugmachasini bosganingizda, u barcha bajarilgan
Todo
o'chiradi - Qo'shish tugmachasini bosganingizda, u
Todo
ro'yxatiga quyidagi qiymatlar bilanTodo
qo'shishi kerak:-
id
: Server tomoni hisoblangan identifikatori boshqa barcha identifikatorlarning maksimali va 1 -
label
:label
uchun Label maydonining qiymati -
completed
:false
o'rnatildi
-
Vue-ga birinchi qadamlarimiz
Birinchi qadam - bu ramkani yuklash. Yuqoridagi maxsus vue.js
faylimiz uchun havolani allaqachon sozlaganmiz.
document.addEventListener('DOMContentLoaded', () => { //1 // The next JavaScript code snippets will be inside the block }
- DOM yuklashni tugatgandan so'ng blokni ishga tushiring
Keyingi qadam Vue-ga sahifaning bir qismini boshqarishga ruxsat berishdir. HTML tomonida biz Vue qaysi yuqori darajadagi qismini boshqarishini hal qilishimiz kerak. Biz ixtiyoriy <div>
tanlashimiz va kerak bo'lganda uni keyinroq o'zgartirishimiz mumkin.
<div id="app"> </div>
JavaScript tomonida biz oldingi HTML <div>
ning CSS selektoridan o'tib, ilova yaratamiz.
Vue.createApp({}).mount('#app');
Shu nuqtada, sahifa yuklanganda biz Vue-ni ishga tushiramiz, lekin ko'rinadigan hech narsa sodir bo'lmaydi.
Keyingi qadam Vue shablonini yaratishdir. Vue shabloni bu Vue tomonidan boshqariladigan oddiy HTML <template>
. Siz Vue-ni Javascript-da belgilashingiz mumkin, lekin men buni HTML sahifasida qilishni afzal ko'raman.
Sarlavhani ko'rsatadigan ildiz shablonidan boshlaylik.
<template id="todos-app"> <!--1--> <h1>{{ title }}</h1> <!--2--> </template>
- Oson bog'lash uchun identifikatorni o'rnating
-
title
xususiyatidan foydalaning; uni o'rnatish kerak
JavaScript tomonida biz boshqaruv kodini yaratishimiz kerak.
const TodosApp = { props: ['title'], //1 template: document.getElementById('todos-app').innerHTML, }
- HTML shablonida ishlatiladigan
title
xususiyatini e'lon qiling
Nihoyat, ilovani yaratishda biz ushbu ob'ektni o'tkazishimiz kerak:
Vue.createApp({ components: { TodosApp }, //1 render() { //2 return Vue.h(TodosApp, { //3 title: window.vueData.title, //4 }) } }).mount('#app');
- Komponentni sozlang
- Vue
render()
funksiyasini kutadi -
h()
giperskript uchun ob'ekt va uning xususiyatlaridan virtual tugun yaratadi -
title
xususiyatini server tomonida yaratilgan qiymat bilan ishga tushiring
Ushbu nuqtada Vue sarlavhani ko'rsatadi.
Asosiy o'zaro ta'sirlar
Ushbu nuqtada, foydalanuvchi belgilash katakchasini bosganida amalni amalga oshirishimiz mumkin: u server tomonida yangilanishi kerak.
Birinchidan, men Todo
ko'rsatadigan jadval uchun yangi Vue shablonini qo'shdim. Xabarni uzaytirmaslik uchun uni batafsil tavsiflashdan qochaman. Agar qiziqsangiz, manba kodini ko'rib chiqing.
Mana boshlang'ich satr shablonining kodi, mos ravishda JavaScript va 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>
-
Todo
identifikatorini ko'rsating -
Todo
yorlig'ini ko'rsating - Agar
completed
atributtrue
bo'lsa, katakchani belgilang
Vue @
sintaksisi orqali hodisalarni boshqarishga imkon beradi.
<input type="checkbox" :checked="todo.completed" @click="check" />
Foydalanuvchi chiziqni bosganida, Vue shablonning check()
funksiyasini chaqiradi. Biz ushbu funktsiyani setup()
parametrida aniqlaymiz:
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 } }
- Biz keyinchalik unga kirishimiz uchun
props
qatorini qabul qiling - Vue qo'ng'iroqni boshlagan
event
o'tadi - Axios - bu HTTP qo'ng'iroqlarini soddalashtiradigan JavaScript lib
- Server tomoni API taqdim etishi kerak ; bu post doirasidan tashqarida, lekin manba kodini tekshirib ko'ring.
- JSON foydali yuk
- Biz barcha belgilangan funksiyalarni HTML dan foydalanish imkoniyatini yaratish uchun qaytaramiz
Mijoz tomoni modeli
Oldingi bo'limda men ikkita xatoga yo'l qo'ydim:
- Men hech qanday mahalliy modelni boshqarmadim
- Men HTTP javobining chaqiruv usulidan foydalanmadim
Biz buni keyingi xususiyatni, ya'ni tugallangan vazifalarni tozalash orqali amalga oshiramiz.
Endi biz Vue orqali voqealarni qanday boshqarishni bilamiz:
<button class="btn btn-warning" @click="cleanup">Cleanup</button>
TodosApp
ob'ektida biz bir xil nomdagi funktsiyani qo'shamiz:
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 } }
- Yuqoridagi kabi
- Axios HTTP chaqiruvining avtomatik JSON konvertatsiyasini taklif qiladi
-
state
- bu modelni saqlaydigan joy
Vue semantikasida Vue modeli biz reaktiv bo'lishni xohlaydigan ma'lumotlar atrofidagi o'rashdir. Reaktiv ko'rinish va model o'rtasidagi ikki tomonlama bog'lanishni anglatadi. Biz mavjud qiymatni ref()
usuliga o'tkazish orqali reaktiv qilishimiz mumkin:
Composition API'da reaktiv holatni e'lon qilishning tavsiya etilgan usuli
ref()
funktsiyasidan foydalanishdir.
ref()
argumentni oladi va uni .value xususiyatiga ega ref ob'ektiga o'ralgan holda qaytaradi.
Komponent shablonidagi referatlarga kirish uchun ularni komponentning
setup()
funksiyasidan e'lon qiling va qaytaring.
Keling buni bajaramiz:
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');
- Yuqorida aytib o'tilganidek, Thymeleaf orqali HTML sahifasida ma'lumotlar to'plamini oling
-
title
o'rnatish usulini o'zgartiramiz. Bu shart emas, chunki ikki tomonlama bog'lanish yo'q - biz mijoz tomoni sarlavhasini yangilamaymiz, lekin men barcha qiymatlar bo'ylab ishlashni izchil saqlashni afzal ko'raman - Vue kutganidek, hakamlarni qaytaring
- Qarang, oyim, men JavaScript tarqatish operatoridan foydalanmoqdaman
- Ob'ektning
state
atributini sozlang
Ayni paytda bizda reaktiv mijoz modeli mavjud.
HTML tomonida biz tegishli Vue atributlaridan foydalanamiz:
<tbody> <tr is="vue:todo-line" v-for="todo in todos" :key="todo.id" :todo="todo"></tr> <!--1-2--> </tbody>
-
Todo
ob'ektlari ro'yxatini aylantiring -
is
atributi brauzer HTMLni tahlil qilish usulini engish uchun juda muhimdir. Qo'shimcha ma'lumot olish uchun Vue hujjatlariga qarang
Men yuqorida tegishli shablonni tasvirlab berdim.
Modelni yangilash
Endi biz yangi xususiyatni amalga oshirishimiz mumkin: mijozdan yangi Todo
qo'shing. Qo'shish tugmasini bosganimizda biz Label maydoni qiymatini o'qiymiz, ma'lumotlarni API ga yuboramiz va javob bilan modelni yangilaymiz.
Mana yangilangan 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 } } }
- Qo'llanishi funksiya bilan cheklangan sarlavha atrofida reaktiv o'ram yarating
-
create()
funktsiyasi to'g'ri - API chaqiruvi tomonidan qaytarilgan yangi JSON ob'ektini
Todo
ro'yxatiga qo'shing - Maydon qiymatini tiklang
- O'chirishda butun ro'yxatni almashtiring; mexanizmi bir xil
HTML tomonida biz tugma qo'shamiz va create()
funksiyasiga bog'laymiz. Xuddi shunday, biz Label maydonini qo'shamiz va uni modelga bog'laymiz.
<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()
funksiyasini HTML tugmasi bilan bog‘laydi. U uni asinxron tarzda chaqiradi va qo'ng'iroq orqali qaytarilgan yangi element bilan reaktiv Todo
ro'yxatini yangilaydi. Belgilangan Todo
obyektlarini olib tashlash uchun "Tozalash" tugmasi uchun ham xuddi shunday qilamiz.
E'tibor bering, men kodni kerak bo'lgandan ko'ra murakkablashtirmaslik uchun hech qanday xatolik kodini ataylab amalga oshirmaganman. Birinchi tajriba uchun yetarli tushunchaga ega bo‘lganimiz uchun shu yerda to‘xtayman.
Xulosa
Ushbu postda men Vue bilan SSR ilovasini ko'paytirish bo'yicha birinchi qadamlarimni qo'ydim. Bu juda oddiy edi. Men duch kelgan eng katta muammo Vue-ning chiziq shablonini almashtirishi edi: men hujjatlarni ko'p o'qimaganman va is
atributini o'tkazib yuborganman.
Biroq, men JavaScript-ning bir nechta qatorlarini yozishim kerak edi, garchi men HTTP qo'ng'iroqlarida yordam berish uchun Axios-dan foydalanganman va xatolarni boshqara olmaganman.
Keyingi postda men Alpine.js bilan bir xil xususiyatlarni amalga oshiraman.
Ushbu postning toʻliq manba kodini GitHub’da topish mumkin:
Oldinga boring: