Алдыңғы жазбамда мен негізін салуға негіз салдым; енді «шынайы үшін» басталатын уақыт.
Мен 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 жағында 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
нысандарының статикалық тізімін өткізіңіз
Егер сіз 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>
Өткен аптадағы мақалада түсіндірілгендей, Thymeleaf артықшылықтарының бірі - ол статикалық файлдарды көрсетуге де, серверлік көрсетуге де мүмкіндік береді. Сиқырлы жұмыс істеу үшін мен клиенттік жолды, яғни src
және серверлік жолды, яғни th:src
жолын көрсетемін.
Енді Vue кодын қарастырайық.
Біз бірнеше мүмкіндіктерді іске асырғымыз келеді:
Todo
элементтерін көрсетуі керекTodo
орындалған құсбелгіні басқан кезде, ол completed
төлсипатты орнату/өшіру керекTodo
жоядыTodo
тізіміне Todo
қосуы керек:id
: барлық басқа идентификаторлардың максимумы ретінде сервер тарапынан есептелген идентификатор плюс 1label
: label
арналған Белгі өрісінің мәніcompleted
: false
мәніне орнатылды Бірінші қадам - фреймворкті жүктеу. Жоғарыдағы пайдаланушы vue.js
файлы үшін сілтемені орнатып қойғанбыз.
document.addEventListener('DOMContentLoaded', () => { //1 // The next JavaScript code snippets will be inside the block }
Келесі қадам - 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, }
title
сипатын жариялаңыз
Соңында, біз қолданбаны жасаған кезде осы нысанды өткізуіміз керек:
Vue.createApp({ components: { TodosApp }, //1 render() { //2 return Vue.h(TodosApp, { //3 title: window.vueData.title, //4 }) } }).mount('#app');
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
массивін қабылдаңызevent
өтедіАлдыңғы бөлімде мен екі қате жібердім:
Біз мұны келесі мүмкіндікті, яғни аяқталған тапсырмаларды тазалау арқылы орындаймыз.
Біз енді 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 } }
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');
title
орнату жолын өзгертеміз. Бұл қажет емес, өйткені екі жақты байланыстыру жоқ - біз клиенттік тақырыпты жаңартпаймыз, бірақ мен өңдеуді барлық мәндер бойынша когерентті сақтауды қалаймын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()
функциясы дұрыс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 сайтында табуға болады:
Әрі қарай жүріңіз: