HTML5-Tutorium: JavaScript: Hello World Vue 03
Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:
Korrektheit: 3 (zu größeren Teilen überprüft) |
Umfang: 4 (unwichtige Fakten fehlen) |
Quellenangaben: 3 (wichtige Quellen vorhanden) |
Quellenarten: 5 (ausgezeichnet) |
Konformität: 3 (gut) |
Inhalt | Teil 1 | Teil 2 | Teil 3 | Teil 4 | Teil 5 | Teil 6 | Vue 1 | Vue 2 | Vue 3 | Vue 4 | Vue 5 | Vue 6
Musterlösung
Git-Repository, git checkout v03
(JavaScript)
Git-Repository (TypeScript), git checkout v03
Stores mit Hilfe von Klassen:
Git-Repository, git checkout v03b
(JavaScript)
Git-Repository (TypeScript), git checkout v03b
Anwendungsfälle (Use Cases)
Gegenüber dem ersten und zweiten Teil des Vue-Tutoriums ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.
Aufgabe
Aufgabe: Speichere den Zustand der Anwendung (Model) in Store-Objekten, um die künftige Modularisierung (Version v04) zu unterstützen.
In diesem Tutorium sollen die Daten in einem Store außerhalb der Komponenten gespeichert werden.
Mögliche Storekonzepte
- vuex (veraltet, wird nur noch gewartet, angeblich nicht mehr weiterentwickelt, aber Version 4 existiert)
- Pinia (der Nachfolger von vuex; einfacher zu benutzen; Vue-3- und Vue-2-Paradigmen werden unterstützt)
- ohne Bibliothek direkt mit
ref
,reactive
undcomputed
aus Vue 3.2 (vgl. Vue 3 — The New Store)
Wir verwenden Pinia.
Pinia
Zitat:
While our hand-rolled state management solution will suffice in simple scenarios, there are many more things to consider in large-scale production applications:
- Stronger conventions for team collaboration
- Integrating with the Vue DevTools, including timeline, in-component inspection, and time-travel debugging
- Hot Module Replacement
- Server-Side Rendering support
Pinia is a state management library that implements all of the above. It is maintained by the Vue core team, and works with both Vue 2 and Vue 3.
Existing users may be familiar with Vuex, the previous official state management library for Vue. With Pinia serving the same role in the ecosystem, Vuex is now in maintenance mode. It still works, but will no longer receive new features. It is recommended to use Pinia for new applications.
Pinia started out as an exploration of what the next iteration of Vuex could look like, incorporating many ideas from core team discussions for Vuex 5. Eventually, we realized that Pinia already implements most of what we wanted in Vuex 5, and decided to make it the new recommendation instead.
Compared to Vuex, Pinia provides a simpler API with less ceremony, offers Composition-API-style APIs, and most importantly, has solid type inference support when used with TypeScript.
Erstellen eines neuen Projektzweigs
Erstellen Sie einen neuen Projektzweig (branch) innerhalb von hello_world_vue
:
git checkout v02 # Wechsle in den Branch v02
git checkout -b v03 # Klone v02 in einen neuen Branch v03
npm i
Initialisierung von Pinia
Pinia muss als reguläre Dependency installiert werden, da das Paket in den produktiven Code integriert wird.
npm i pinia // NICHT npm i -D pinia
Pinia wird als Plugin in die App integriert. Dabei ist wichtig, dass das Pina-Plugin-Objekt vor dem eigentlichen App-Objekt erzeugt wird, da Komponenten der App, die Pinia verwenden, darauf angewiesen sind, dass die Pinia-Erzeugung vor der Komponenten-Initialisierung erfolgt.
// src/main.js
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import App from './App.vue'
const pinia = createPinia() // before createApp(...)
window.addEventListener
( 'load',
createApp(App).use(pinia).mount('#app')
)
Erstellen der Stores
StoreSection
Im Section-Store wird gespeichert, welche Section der Single-Page-Anwendung dem Benutzer aktuell präsentiert wird.
// src/store/StoreSection.js
import { defineStore } from 'pinia'
import { ref } from 'vue'
const storeSection =
defineStore
( 'section', // must be unique
() =>
{ const
currentSection =
ref(''),
init =
p_section =>
currentSection.value = p_section,
visibility =
p_section =>
currentSection.value !== p_section ? 'hidden' : '',
change =
init // change macht dasselbe wie init
return { init, visibility, change }
}
)
export default storeSection
StoreGreeting
Im Greeting-Store werden die Daten zur Begrüßung des Benutzers gespeichert.
// src/store/StoreGreeting.js
import { defineStore } from 'pinia'
import { reactive, toRef, computed } from 'vue'
const
storeGreeting =
defineStore
( 'greeting',
() =>
{ const
state =
reactive({ name: '', stranger: 'Stranger', hello: 'Hello, $1!' }),
init =
(p_state = {}) =>
{ Object.assign(state, p_state) },
name =
toRef(state, 'name'),
sayHello =
p_name => state.hello.replace('$1', p_name),
helloStranger =
computed(() => sayHello(state.stranger)),
hello =
computed(() => sayHello(state.name))
return { init, name, helloStranger, hello }
}
)
export default storeGreeting
Einbinden der Stores in einer Komponente
<!-- src/components/HelloWorld.vue -->
<script setup>
import { onMounted, onUnmounted } from 'vue'
import storeSection from '@/store/StoreSection'
import storeGreeting from '@/store/StoreGreeting'
import ControllerKey from '@/controller/ControllerKey'
const
section = storeSection(),
greeting = storeGreeting(),
sayHello = () => section.change('hello'),
controllerKey = new ControllerKey('Enter', sayHello, 'input_name')
section.init('form')
//greeting.init({ hello: 'Hi, $1!', stranger: 'Nobody'})
onMounted (() => controllerKey.add())
onUnmounted(() => controllerKey.remove())
</script>
Zum Vergleich noch einmal das Skript ohne Store
<!-- src/components/HelloWorld.vue without store -->
<script setup >
import { ref, computed, onMounted, onUnmounted } from 'vue'
import ControllerKey from '@/controller/ControllerKey'
const
section = ref('form'),
helloStranger = ref('Hello, Stranger'),
name = ref(''),
hello = computed(() => `Hello, ${name.value}!`),
visibility = p_section =>
p_section !== section.value ? 'hidden' : '',
sayHello = () => section.value = 'hello',
autofocus = () => document.getElementById('input_name').focus(),
controllerKey = new ControllerKey('Enter', sayHello, 'input_name')
onMounted (...)
onUnmounted(...)
</script>
Anpassung des Templates
Das Template muss angepasst werden. Man muss nun auf die Store-Objekte zugreifen.
<!-- src/components/HelloWorld.vue -->
<template>
<section id="section_form" v-bind:class="section.visibility('form')">
<h1>{{greeting.helloStranger}}</h1>
<form>
<div>
<label for="input_name">What is your name?</label>
<input id="input_name" type="text" autofocus
v-model="greeting.name"
/>
</div>
<div>
<input id="button_reset" type="reset" value="Reset"/>
<input id="button_submit" type="button" value="Say hello"
v-on:click="sayHello"
/>
</div>
</form>
</section>
<section id="section_hello" v-bind:class="section.visibility('hello')">
<h1>{{greeting.hello}}</h1>
<p>Welcome to Web Programming!</p>
</section>
</template>
Fortsetzung des Tutoriums
Sie sollten nun Teil 4 des Vue-Tutoriums bearbeiten. Nun wird die Anwendung modularisiert.
Quellen
- Kowarschick (WebProg): Wolfgang Kowarschick; Vorlesung „Web-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2024; Quellengüte: 3 (Vorlesung)