Алдыңғы жазбамда мен негізін салуға негіз салдым; енді «шынайы үшін» басталатын уақыт.
Мен Vue.js көп естідім. Сонымен қатар, әзірлеушіден менеджерге ауысқан досым маған Vue туралы жақсы нәрселер айтты, бұл менің қызығушылығымды арттырды. Мен оны қарап шығуды шештім: бұл мен зерттейтін бірінші «жеңіл» JavaScript құрылымы болады - мен жаңадан келген адам тұрғысынан.
Жұмысты орналастыру
Мен соңғы постта WebJars және Thymeleaf түсіндірдім. Мұнда орнату, сервер және клиент жағы.
Сервер жағы
Міне, мен екеуін де 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>
- Spring Boot өзі; Мен тұрақты, реактивті емес тәсілді шештім
- Spring Boot Thymeleaf интеграциясы
- Клиент жағында Vue нұсқасын көрсетпеу үшін WebJars локаторы
- Vue, ақырында!
Мен Spring Boot жағында Kotlin Router және Bean DSL пайдаланамын:
fun vue(todos: List<Todo>) = router { //1 GET("/vue") { ok().render("vue", mapOf("title" to "Vue.js", "todos" to todos)) //2-3 } }
-
Todo
нысандарының статикалық тізімін өткізіңіз - Төменде қараңыз
- Үлгіні Thymeleaf-ке беріңіз
Егер сіз API әзірлеуге үйренген болсаңыз, body()
функциясымен таныссыз; ол пайдалы жүктемені тікелей қайтарады, мүмкін JSON пішімінде. render()
ағынды көру технологиясына береді, бұл жағдайда Thymeleaf. Ол екі параметрді қабылдайды:
- Көрініс атауы. Әдепкі бойынша, жол
/templates
және префикс.html
; бұл жағдайда Thymeleaf/templates/vue.html
мекенжайында көрініс күтеді - Кілт-мән жұптарының үлгі картасы
Клиенттік
Міне, 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>
- Axios HTTP сұрауларын жасауға көмектеседі
- Vue өзі
- Біздің клиенттік код
- Деректерді орнатыңыз
Өткен аптадағы мақалада түсіндірілгендей, Thymeleaf артықшылықтарының бірі - ол статикалық файлдарды көрсетуге де, серверлік көрсетуге де мүмкіндік береді. Сиқырлы жұмыс істеу үшін мен клиенттік жолды, яғни src
және серверлік жолды, яғни th:src
жолын көрсетемін.
Vue коды
Енді Vue кодын қарастырайық.
Біз бірнеше мүмкіндіктерді іске асырғымыз келеді:
- Бет жүктелгеннен кейін бет барлық
Todo
элементтерін көрсетуі керек -
Todo
орындалған құсбелгіні басқан кезде, олcompleted
төлсипатты орнату/өшіру керек - «Тазалау» түймесін басқан кезде, ол барлық аяқталған
Todo
жояды - Қосу түймешігін басқан кезде, ол келесі мәндері бар
Todo
тізімінеTodo
қосуы керек:-
id
: барлық басқа идентификаторлардың максимумы ретінде сервер тарапынан есептелген идентификатор плюс 1 -
label
:label
арналған Белгі өрісінің мәні -
completed
:false
мәніне орнатылды
-
Vue-ге алғашқы қадамдарымыз
Бірінші қадам - фреймворкті жүктеу. Жоғарыдағы пайдаланушы vue.js
файлы үшін сілтемені орнатып қойғанбыз.
document.addEventListener('DOMContentLoaded', () => { //1 // The next JavaScript code snippets will be inside the block }
- DOM жүктеуді аяқтаған кезде блокты іске қосыңыз
Келесі қадам - Vue-ге беттің бір бөлігін басқаруға мүмкіндік беру. HTML жағында біз Vue жоғарғы деңгейдің қай бөлігін басқаратынын шешуіміз керек. Біз ерікті <div>
таңдай аламыз және қажет болса, оны кейінірек өзгерте аламыз.
<div id="app"> </div>
JavaScript жағында біз алдыңғы HTML <div>
CSS селекторын өткізіп, қолданба жасаймыз.
Vue.createApp({}).mount('#app');
Осы сәтте біз бет жүктелген кезде Vue іске қосамыз, бірақ көрінетін ештеңе болмайды.
Келесі қадам Vue үлгісін жасау болып табылады. Vue үлгісі — Vue басқаратын кәдімгі HTML <template>
. Сіз Javascript-те Vue-ді анықтай аласыз, бірақ мен оны HTML бетінде жасағанды қалаймын.
Тақырыпты көрсете алатын түбірлік үлгіден бастайық.
<template id="todos-app"> <!--1--> <h1>{{ title }}</h1> <!--2--> </template>
- Оңай байлау үшін идентификаторды орнатыңыз
-
title
қасиетін пайдаланыңыз; орнату керек
JavaScript жағында біз басқару кодын жасауымыз керек.
const TodosApp = { props: ['title'], //1 template: document.getElementById('todos-app').innerHTML, }
- HTML үлгісінде қолданылатын
title
сипатын жариялаңыз
Соңында, біз қолданбаны жасаған кезде осы нысанды өткізуіміз керек:
Vue.createApp({ components: { TodosApp }, //1 render() { //2 return Vue.h(TodosApp, { //3 title: window.vueData.title, //4 }) } }).mount('#app');
- Құрамдас бөлікті конфигурациялаңыз
- Vue
render()
функциясын күтеді -
h()
гиперскрипт үшін объект пен оның қасиеттерінен виртуалды түйін жасайды - Сервер жағында жасалған мәнмен
title
сипатын инициализациялаңыз
Осы кезде Vue тақырыпты көрсетеді.
Негізгі өзара әрекеттесулер
Осы сәтте пайдаланушы құсбелгіні басқанда әрекетті орындай аламыз: оны серверлік күйде жаңарту қажет.
Біріншіден, мен Todo
көрсететін кесте үшін жаңа кірістірілген Vue үлгісін қостым. Жазбаны ұзартпау үшін мен оны егжей-тегжейлі сипаттаудан аулақ боламын. Егер сізді қызықтырса, бастапқы кодты қараңыз.
Міне, бастапқы жол үлгісінің коды, сәйкесінше JavaScript және 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
идентификаторын көрсетіңіз -
Todo
белгісін көрсетіңіз -
completed
төлсипатыtrue
болса, құсбелгіні қойыңыз
Vue оқиғаны @
синтаксисі арқылы өңдеуге мүмкіндік береді.
<input type="checkbox" :checked="todo.completed" @click="check" />
Пайдаланушы желіні басқан кезде Vue шаблонның check()
функциясын шақырады. Бұл функцияны 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 } }
- Кейінірек оған қол жеткізуіміз үшін
props
массивін қабылдаңыз - Vue қоңырауды тудырған
event
өтеді - Axios — HTTP қоңырауларын жеңілдететін JavaScript lib
- Сервер жағы API қамтамасыз етуі керек ; бұл осы жазбаның ауқымынан тыс, бірақ бастапқы кодты тексеріңіз.
- JSON пайдалы жүктемесі
- Біз барлық анықталған функцияларды HTML арқылы қолжетімді ету үшін қайтарамыз
Клиенттік модель
Алдыңғы бөлімде мен екі қате жібердім:
- Мен ешқандай жергілікті модельді басқармадым
- Мен HTTP жауабының қоңырау әдісін пайдаланбадым
Біз мұны келесі мүмкіндікті, яғни аяқталған тапсырмаларды тазалау арқылы орындаймыз.
Біз енді Vue арқылы оқиғаларды қалай өңдеу керектігін білеміз:
<button class="btn btn-warning" @click="cleanup">Cleanup</button>
TodosApp
нысанында біз аттас функцияны қосамыз:
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 } }
- Жоғарыдағыдай
- Axios HTTP қоңырауының автоматтандырылған JSON түрлендіруін ұсынады
-
state
- біз үлгіні сақтайтын жер
Vue семантикасында Vue үлгісі - біз реактивті болғымыз келетін деректердің айналасындағы орауыш. Реактивті көрініс пен модель арасындағы екі жақты байланысты білдіреді. Біз бар мәнді ref()
әдісіне беру арқылы реактивті ете аламыз:
Composition API ішінде реактивті күйді жариялаудың ұсынылатын жолы
ref()
функциясын пайдалану болып табылады.
ref()
аргументті қабылдайды және оны .value сипаты бар ref нысанына оралған күйде қайтарады.
Компонент үлгісіндегі сілтемелерге қол жеткізу үшін оларды құрамдастың
setup()
функциясынан жариялаңыз және қайтарыңыз.
Қанекей мынаны істейік:
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');
- Жоғарыда түсіндірілгендей, Thymeleaf арқылы HTML бетіндегі деректер жинағын алыңыз
- Біз
title
орнату жолын өзгертеміз. Бұл қажет емес, өйткені екі жақты байланыстыру жоқ - біз клиенттік тақырыпты жаңартпаймыз, бірақ мен өңдеуді барлық мәндер бойынша когерентті сақтауды қалаймын - Vue күткендегідей рефлектерді қайтарыңыз
- Қараңызшы, ана, мен JavaScript тарату операторын пайдаланып жатырмын
-
state
атрибутталған нысанды теңшеңіз
Осы кезде бізде реактивті клиенттік үлгі бар.
HTML жағында біз сәйкес Vue атрибуттарын қолданамыз:
<tbody> <tr is="vue:todo-line" v-for="todo in todos" :key="todo.id" :todo="todo"></tr> <!--1-2--> </tbody>
-
Todo
нысандарының тізімін айналдырыңыз -
is
атрибуты браузердің HTML талдау әдісімен күресу үшін өте маңызды. Қосымша мәліметтер алу үшін Vue құжаттамасын қараңыз
Мен жоғарыда сәйкес үлгіні сипаттадым.
Модельді жаңарту
Енді біз жаңа мүмкіндікті іске асыра аламыз: клиенттен жаңа Todo
қосыңыз. Қосу түймешігін басқан кезде біз Label өрісінің мәнін оқимыз, деректерді API-ге жібереміз және модельді жауаппен жаңартамыз.
Мұнда жаңартылған код:
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 } } }
- Ауқымы функциямен шектелген тақырыптың айналасында реактивті қаптама жасаңыз
-
create()
функциясы дұрыс - API шақыруы арқылы қайтарылған жаңа JSON нысанын
Todo
тізіміне қосыңыз - Өрістің мәнін қалпына келтіріңіз
- Жою кезінде бүкіл тізімді ауыстырыңыз; механизмі бірдей
HTML жағында біз түймені қосамыз және create()
функциясына байланыстырамыз. Сол сияқты, біз Label өрісін қосып, оны үлгіге байланыстырамыз.
<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()
функциясын HTML түймешігімен байланыстырады. Ол оны асинхронды түрде шақырады және қоңырау арқылы қайтарылған жаңа элементпен реактивті Todo
тізімін жаңартады. Белгіленген Todo
нысандарын жою үшін «Тазалау» түймесі үшін де солай істейміз.
Кодты қажет болғаннан күрделірек етпеу үшін қателерді өңдеу кодын әдейі енгізбегенімді ескеріңіз. Мен осы жерде тоқтаймын, өйткені біз бірінші тәжірибе үшін жеткілікті түсінік алдық.
Қорытынды
Бұл постта мен Vue көмегімен SSR қолданбасын кеңейтудегі алғашқы қадамдарымды жасадым. Бұл өте қарапайым болды. Мен кездестірген ең үлкен мәселе Vue желісі үлгісін ауыстыру болды: мен құжаттаманы көп оқымадым және is
атрибутын жіберіп алдым.
Дегенмен, мен HTTP қоңырауларына көмектесу үшін Axios қолданбасын пайдалансам да, қателерді басқармасам да, JavaScript-тің бірнеше жолын жазуға тура келді.
Келесі постта мен Alpine.js бағдарламасымен бірдей мүмкіндіктерді жүзеге асырамын.
Бұл жазбаның толық бастапқы кодын GitHub сайтында табуға болады:
Әрі қарай жүріңіз: