paint-brush
Proširivanje klijenta pomoću Vue.jsby@nfrankel
Nova istorija

Proširivanje klijenta pomoću Vue.js

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

Predugo; Citati

U ovom postu sam napravio prve korake u proširenju SSR aplikacije pomoću Vuea. Bilo je prilično jednostavno. Najveći problem na koji sam naišao bio je da Vue zamijeni predložak linije: nisam detaljno čitao dokumentaciju i propustio sam atribut is.
featured image - Proširivanje klijenta pomoću Vue.js
Nicolas Fränkel HackerNoon profile picture
0-item


U svom prethodnom postu , postavio sam teren za izgradnju; sada je vrijeme da počnete "zaista".


Čuo sam dosta o Vue.js-u . Osim toga, prijatelj koji je prešao od programera do menadžera rekao mi je dobre stvari o Vue-u, što je dodatno pobudilo moje interesovanje. Odlučio sam da ga pogledam: to će biti prvi "laki" JavaScript framework koji ću proučiti - sa stanovišta početnika, što sam i jesam.

Postavljanje posla

Objasnio sam WebJars i Thymeleaf u prošlom postu. Evo podešavanja, serverske i klijentske strane.

Server-side

Evo kako integrišem oba u 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 sama; Odlučio sam se za redovni, nereaktivni pristup
  2. Spring Boot Thymeleaf integracija
  3. WebJars lokator, kako biste izbjegli specificiranje Vue verzije na strani klijenta
  4. Vue, konačno!


Koristim Kotlin Router i Bean DSL-ove na strani Spring Boot-a:


 fun vue(todos: List<Todo>) = router { //1 GET("/vue") { ok().render("vue", mapOf("title" to "Vue.js", "todos" to todos)) //2-3 } }
  1. Proslijedite statičku listu Todo objekata
  2. Vidi ispod
  3. Proslijedite model Thymeleaf-u


Ako ste navikli da razvijate API-je, upoznati ste sa funkcijom body() ; direktno vraća korisni teret, vjerovatno u JSON formatu. render() prosljeđuje tok tehnologiji prikaza, u ovom slučaju Thymeleaf. Prihvata dva parametra:


  1. Ime pogleda. Podrazumevano, putanja je /templates , a prefiks je .html ; u ovom slučaju, Thymeleaf očekuje pregled na /templates/vue.html
  2. Model mape parova ključ/vrijednost

Na strani klijenta

Evo koda na HTML strani:


 <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 pomaže u izradi HTTP zahtjeva
  2. Vue sam
  3. Naš kod na strani klijenta
  4. Podesite podatke


Kao što je objašnjeno u prošlosedmičnom članku, jedna od prednosti Thymeleaf-a je ta što omogućava i statičko prikazivanje datoteka i renderiranje na strani servera. Da bi magija funkcionirala, specificiram putanju na strani klijenta, tj . src , i putanju na strani servera, tj . th:src .


Vue kod

Sada, zaronimo u Vue kod.

Želimo implementirati nekoliko funkcija:


  1. Nakon učitavanja stranice, stranica bi trebala prikazati sve Todo stavke
  2. Kada kliknete na polje za potvrdu Todo , trebalo bi postaviti/poništiti completed atribut
  3. Kada kliknete na dugme Čišćenje , briše se svi završeni Todo
  4. Kada kliknete na dugme Dodaj , trebalo bi da dodate Todo na listu Todo sa sledećim vrednostima:
    • id : izračunati ID na strani servera kao maksimum svih ostalih ID-a plus 1
    • label : vrijednost polja Label za label
    • completed : postavljeno na false

Naši prvi koraci u Vue

Prvi korak je pokretanje okvira. Već smo postavili referencu za našu prilagođenu datoteku vue.js iznad.


 document.addEventListener('DOMContentLoaded', () => { //1 // The next JavaScript code snippets will be inside the block }
  1. Pokrenite blok kada DOM završi učitavanje


Sljedeći korak je da dozvolite Vueu da upravlja dijelom stranice. Što se tiče HTML-a, moramo odlučiti kojim dijelom najvišeg nivoa Vue upravlja. Možemo odabrati proizvoljan <div> i promijeniti ga kasnije ako je potrebno.


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


Na strani JavaScripta, kreiramo aplikaciju , prosljeđujući CSS selektor prethodnog HTML-a <div> .


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


U ovom trenutku pokrećemo Vue kada se stranica učita, ali se ništa vidljivo ne dešava.


Sljedeći korak je kreiranje Vue predloška . Vue šablon je običan HTML <template> kojim upravlja Vue. Možete definisati Vue u Javascript-u, ali ja radije to radim na HTML stranici.


Počnimo s korijenskim predloškom koji može prikazati naslov.


 <template id="todos-app"> <!--1--> <h1>{{ title }}</h1> <!--2--> </template>
  1. Postavite ID za jednostavno vezivanje
  2. Koristite svojstvo title ; ostaje da se postavi


Na strani JavaScripta, moramo kreirati upravljački kod.


 const TodosApp = { props: ['title'], //1 template: document.getElementById('todos-app').innerHTML, }
  1. Deklarirajte svojstvo title , ono koje se koristi u HTML šablonu


Konačno, moramo proslijediti ovaj objekt kada kreiramo aplikaciju:


 Vue.createApp({ components: { TodosApp }, //1 render() { //2 return Vue.h(TodosApp, { //3 title: window.vueData.title, //4 }) } }).mount('#app');
  1. Konfigurišite komponentu
  2. Vue očekuje funkciju render()
  3. h() za hiperscript kreira virtuelni čvor od objekta i njegovih svojstava
  4. Inicijalizirajte svojstvo title vrijednošću generiranom na strani servera


U ovom trenutku, Vue prikazuje naslov.

Osnovne interakcije

U ovom trenutku možemo implementirati akciju kada korisnik klikne na potvrdni okvir: treba ga ažurirati u stanju na strani servera.

Prvo sam dodao novi ugniježđeni Vue predložak za tabelu koja prikazuje Todo . Da ne bih produžio post, izbegavaću da ga detaljno opisujem. Ako ste zainteresovani, pogledajte izvorni kod .


Evo koda početne linije predloška, odnosno JavaScript i 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. Prikažite Todo id
  2. Prikažite oznaku Todo
  3. Označite polje ako je njegov completed atribut true


Vue dozvoljava rukovanje događajima putem @ sintakse.


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


Vue poziva funkciju check() predloška kada korisnik klikne na liniju. Ovu funkciju definiramo u parametru 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. Prihvatite niz props , kako bismo mu kasnije mogli pristupiti
  2. Vue prosljeđuje event koji je pokrenuo poziv
  3. Axios je JavaScript biblioteka koja pojednostavljuje HTTP pozive
  4. Strana servera mora da obezbedi API; to je izvan okvira ovog posta, ali slobodno provjerite izvorni kod.
  5. JSON nosivost
  6. Vraćamo sve definirane funkcije kako bismo im učinili dostupnim iz HTML-a

Model na strani klijenta

U prethodnom dijelu napravio sam dvije greške:


  • Nisam upravljao ni jednim lokalnim modelom
  • Nisam koristio metod poziva HTTP odgovora


To ćemo učiniti implementacijom sljedeće funkcije, a to je čišćenje dovršenih zadataka.


Sada znamo kako upravljati događajima putem Vuea:


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


Na objekt TodosApp dodajemo funkciju istog imena:


 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. Kao gore
  2. Axios nudi automatsku JSON konverziju HTTP poziva
  3. state je mjesto gdje pohranjujemo model


U semantici Vuea, Vue model je omot oko podataka za koje želimo da budu reaktivni . Reaktivno znači dvosmjerno povezivanje pogleda i modela. Postojeću vrijednost možemo učiniti reaktivnom tako što ćemo je proslijediti metodi ref() :


U Composition API-ju, preporučeni način za deklariranje reaktivnog stanja je korištenje funkcije ref() .


ref() uzima argument i vraća ga umotanog unutar ref objekta sa svojstvom .value.


Da biste pristupili referencama u šablonu komponente, deklarirajte ih i vratite ih iz funkcije setup() komponente.


-- Proglašavanje reaktivnog stanja


uradimo to:


 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. Nabavite skup podataka na HTML stranici, putem Thymeleaf-a, kako je gore objašnjeno
  2. Mijenjamo način na koji postavljamo title . Nije potrebno jer nema dvosmjernog povezivanja - ne ažuriramo naslov na strani klijenta, ali radije održavam koherentno rukovanje za sve vrijednosti
  3. Vratite sudije, prema Vueovim očekivanjima
  4. Vidi, mama, ja koristim JavaScript operator širenja
  5. Konfigurirajte atribute objekta iz state


U ovom trenutku imamo reaktivni model na strani klijenta.


Na strani HTML-a koristimo relevantne Vue atribute:


 <tbody> <tr is="vue:todo-line" v-for="todo in todos" :key="todo.id" :todo="todo"></tr> <!--1-2--> </tbody>
  1. Pređite preko liste Todo objekata
  2. Atribut is je ključan da se nosi sa načinom na koji pretraživač analizira HTML. Pogledajte Vue dokumentaciju za više detalja

Gore sam opisao odgovarajući šablon.

Ažuriranje modela

Sada možemo implementirati novu funkciju: dodati novi Todo od klijenta. Kada kliknemo na dugme Dodaj , čitamo vrijednost polja Label , šaljemo podatke API-ju i osvježavamo model odgovorom.


Evo ažuriranog koda:


 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. Napravite reaktivni omot oko naslova čiji je opseg ograničen na funkciju
  2. Ispravna funkcija create()
  3. Dodajte novi JSON objekat koji je vratio API poziv na listu Todo
  4. Resetirajte vrijednost polja
  5. Zamijenite cijelu listu prilikom brisanja; mehanizam je isti


Na HTML strani, dodajemo dugme i vezujemo se za funkciju create() . Isto tako, dodajemo polje Label i povezujemo ga sa modelom.


 <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 vezuje funkciju create() za HTML dugme. Poziva ga asinhrono i osvježava reaktivnu Todo listu novom stavkom koju je vratio poziv. Isto radimo za dugme Čišćenje , da uklonimo označene Todo objekte.


Imajte na umu da nisam namjerno implementirao nikakav kod za rukovanje greškama kako bih izbjegao da kod bude složeniji nego što je potrebno. Ovdje ću se zaustaviti jer smo stekli dovoljno uvida za prvo iskustvo.

Zaključak

U ovom postu sam napravio prve korake u proširenju SSR aplikacije pomoću Vuea. Bilo je prilično jednostavno. Najveći problem na koji sam naišao bio je da Vue zamijeni predložak linije: nisam detaljno čitao dokumentaciju i propustio sam atribut is .


Međutim, morao sam da napišem dosta redova JavaScript-a, iako sam koristio Axios da mi pomogne sa HTTP pozivima i nisam upravljao greškama.


U sljedećem postu implementirat ću iste karakteristike sa Alpine.js.


Kompletan izvorni kod za ovaj post možete pronaći na GitHubu:

Idi dalje:



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

HANG TAGS

OVAJ ČLANAK JE PREDSTAVLJEN U...