HTML5-Tutorium: JavaScript: Hello World Vue 02
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
Musterlösung
v02: index.html
(HTML validate, CSS validate, Google PageSpeed)
Git-Repository, git checkout v02
(JavaScript)
Anwendungsfälle (Use Cases)
Gegenüber dem ersten Teil des Vue-Tutoriums ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.
Aufgabe
Ergänze einen Keyup-Event-Handler, so dass das Name mit Hilfe der Entertaste übergeben werden kann, wenn der Fokus auf dem Namenfeld liegt.
Erstellen eines neuen Projektzweigs
Erstellen Sie einen neuen Projektzweig (branch) innerhalb von hello_world_vue
:
git checkout v01 # Wechsle in den Branch v01
git checkout -b v02 # Klone v01 in einen neuen Branch v02
npm i
MVC-Prozess

Zur Lösung der Aufgabe wird eine eigene Controller-Klasse geschrieben.
Dieser Lösung liegt der MVC-Prozess zu Grunde: Die Anwendung besteht aus Model, Views und Controller.
Das Model enthalt den aktuellen Zustand des Systems in Form von Daten (zum Beispiel die Position und den Radius eines Kreises).
Ein (oder auch mehrere Views) visualisieren Daten aus dem Model. So wird beispielsweise der zuvor genannte Kreis in einem durch den Bildschirm vorgegebenen Koordinatensystem an die im Model gespeicherte Position mit dem passenden Radius gezeichnet. Die View agieren als Observer. Das heißt, sie lauschen auf Änderungen am Model und und aktualisieren sich gegebenenfalls.
Der Benutzer (User) nimmt die Visualisierungen wahr (auch als Observer). Er kann überdies mittels so genannten Controllern mit der Anwendung interagieren. Die Controller reagieren auf Devices wie Maus und Tastatur. Der Benutzer kann mit Hilfe derartiger Devices auch Formulare, die in der View enthalten sind, ausfüllen. Änderungen, die der Benutzer (mit Hilfe von geeigneten Devices) an einer View vornimmt, führen zu Änderungen im Model. Das heißt, die meisten Benutzeraktionen haben schlussendlich Änderungen im Model zur Folge, die dann wieder von der View angezeigt werden.
Es gibt noch eine spezielle Kategorie von Controller-Devices: Force Feedback Controller. Diese reagieren z. B. mittels Vibration auf bestimmte Modelländerungen. Force Feedback Controller sind daher in der Regel bidirektional mit dem Model verknüpft.
Key Controller
Man könnte die schon bekannte Funktion sayHelloOnEnter
im Konstantenbereich der
HelloWorld-Komponente definieren und in den Funktionen onMounted
sowie on onUnmounted
aktivieren bzw. deaktivieren.
function sayHelloOnEnter(p_event)
{ if ( p_event.key === 'Enter'
&& p_event.target.id === 'input_name'
)
{ // Prevent other handlers from handling the keypress event.
p_event.preventDefault();
p_event.stopPropagation();
sayHello();
}
}
onMounted (() => window.addEventListener ('keydown', sayHelloOnEnter))
onUnmounted(() => window.removeEventListener('keydown', sayHelloOnEnter))
Besser ist es allerdings, ein Modul zu definieren, das diese Funktionalität zur Verfügung stellt. Damit trennt man den Controller sehr schön vom Model. Deshalb ist im Sinne von Bertrand Meyer, diese Version zu bevorzugen.
Die Kommentare werden später zur automatischen Generierung einer Dokumentation mittels JSDoc benötigt.
<!-- @/controller/controllerKey -->
/**
* When the key <code>p_key</code> is pressed while the focus is
* on the HTML element with the id <code>p_target_id</code>,
* the callback function is invoked.
*
* @param { string } p_key
* The name of a keyboard key
* @param { string } p_target_id
* The id of the DOM element
* @param { function } p_callback
* A callback function
*/
function controllerKey(p_key, p_target_id, p_callback)
{ return (p_event) =>
{ if ( p_event.key === p_key
&& p_event.target.id === p_target_id
)
{ // Prevent other handlers from handling the keypress event.
p_event.preventDefault();
p_event.stopPropagation();
p_callback();
}
}
}
export default controllerKey
Diese Funktion kann nun in das Modul HelloWorld.vue
importiert und dort aktiviert werden.
<script setup>
...
import controllerKey from '@/controller/controllerKey'
const
...
sayHelloOnEnter = controllerKey('Enter', inputId, sayHello)
onMounted
( () =>
{ window.addEventListener('keydown', sayHelloOnEnter);
...
}
)
onUnmounted
( () =>
{ window.removeEventListener('keydown', sayHelloOnEnter);
...
}
)
Jetzt sollte die Anwendung auch per Enter-Taste korrekt bedient werden können.
ControllerKey: Klasse zum Agieren mit Keyboardevents
Alternativ kann man eine wiederverwendbare Controllerklasse definieren.
Die Aufgabe von Objekten dieser Klasse ist es, auf bestimmte Keyboard-Aktionen des Benutzers hin, sofern sich der HTML-Fokus auf bestimmten HTML-Fomularfeldern befindet, eine Callback-Funktion aufzurufen. Im Gegensatz zur obigen Funktion kann man mehrere Keys und mehrereDOM-IIDs angeben, für die bei Betätigung einer dieser Tasten die Callback-Funktion ausgeführt werden soll.
Außerdem stellt die Klasse zwei Methoden add
und remove
bereit, mit denen
ein zugehöriges Controller-Objekt aktiviert bzw. deaktiviert werden kann.
Hier ist die Frage, ob die zusätzlich Funktionalität wirklich benötigt wird. Falls nein, wäre evtl. eine einfachere Klasse sinnvoll, die nicht mehr Funktionalität als die obige Funktion biete, dafür aber kleiner ist und daher weniger Bandbreite beim Laden durch den Browser verbraucht.
Beachten Sie, dass die Funktion ControllerKey
und die Klasse ControllerKeys
heißt.
Eigentlich würde ich die Namens-Konvention bevorzugen, sie gleich zu benennen, und nur durch den Anfangsbuchstaben Funktion und Klasse zu unterscheiden. Ein kleines „c“ steht für ein Funktion, ein großes „C“ für eine Klasse. Aber leider unterscheidet Windows diese beiden Dateinamen nicht. Daher habe ich an
ControllerKey
hinten ein s
angefügt: ControllerKeys
. Da symbolisiert, dass ein Objekt dieser Klasse mehrere Tasten (Keys) auf einmal überwachen kann.
/**
* @class ControllerKey
*/
class ControllerKey
{ #v_key_events;
#f_callback;
/**
* @param { string | Array<string> } p_keys
* The name of a keyboard key or an array of such names
* @param { string | Array<string> | null } p_targets
* The id of an HTML element or an array of such ids.
* @param { function } p_callback
* (p_key?: string, p_target?: string) => void<br>
* A callback function that is called when focus is
* on an HTML element with a matching id and if a key event
* occurs for some of the stated keys.
* @param { 'keydown' | 'keyup' | 'keypress' } p_key_events
*/
constructor(p_keys,p_targets, p_callback, p_key_events = 'keydown')
{ this.#v_key_events = typeof p_key_events === 'string'
? [p_key_events]
: p_key_events;
const
c_keys = typeof p_keys === 'string' ? [p_keys] : p_keys,
c_targets = typeof p_targets === 'string' ? [p_targets] : p_targets
this.#f_callback =
p_event =>
{ const
c_key = p_event.key,
c_target = p_event.target.id
if (c_keys.includes(c_key) && (!c_targets || c_targets.includes(c_target)))
{ // Prevent other handlers from handling the keypress event.
p_event.preventDefault();
p_event.stopPropagation();
// Invoke the callback function
p_callback(c_key, c_target);
}
}
}
/** Adds the key handler described by this object as keyboard event handler. */
add()
{ for (const l_key_event of this.#v_key_events)
{ window.addEventListener(l_key_event, this.#f_callback) }
}
/** Removes the key handler described by this object as keyboard event handler. */
remove()
{ for (const l_key_event of this.#v_key_events)
{ window.removeEventListener(l_key_event, this.#f_callback) }
}
}
export default ControllerKey
Key-Controller einbinden
Die zuvor definierte Klasse kann nun verwendet werden. Dazu wird sie in HelloWorld.vue
importiert.
Dort wird ein neues ControllerKey-Objekt definiert. Dieses wird aktiviert, wenn die Komponenten in eine View eingebunden wird (mounted) wird und deaktiviert, wenn sie wieder entfernt wird (unmounted).
<script setup>
...
import ControllerKey from '@/controller/ControllerKeys'
const
...,
sayHelloOnEnter = new ControllerKey('Enter', inputId, sayHello)
onMounted
( () =>
{ sayHelloOnEnter.add();
window.addEventListener('visibilitychange', autofocus);
autofocus();
}
)
onUnmounted
( () =>
{ sayHelloOnEnter.remove();
window.removeEventListener('visibilitychange', autofocus);
}
)
</script>
JSDoc
Wenn wir schon dabei sind, können wir auch gleich noch die JSDoc aktivieren. JSDoc generiert aus gemäß dem JSDoc-Standard kommentierten ECMAScript-/Typescript-Dateien automatisch eine HTML-Dokumentation.
Installieren Sie zunächst JSDOc:
npm i -D jsdoc
npm i -D docdash // oder ein anderes Stylepaket Ihrer Wahl
und erstellen Sie eine zugehörige Konfigurationsdatei jsdoc.config.json
:
{ "opts":
{ "encoding": "utf8",
"destination": "./doc/",
"recurse": true,
"template": "node_modules/docdash"
}
}
Fügen Sie dann den nachfolgenden Befehl in das Objekt scripts
der Datei package.json
ein:
"jsdoc": "jsdoc -c jsdoc.config.json src"
Wenn Sie nun npm run jsdoc
ins Terminal tippen, wird die zugehörige Dokumentation im Ordner doc
erzeugt. Diese enthält nur eine Dokumentation für die Dateien controllerKey.js
und ControllerKeys.js
, da dies die einzigen Dateien ist, die JSDoc-Kommentare enthalten.
Fortsetzung des Tutoriums
Sie sollten nun Teil 3 des Vue-Tutoriums bearbeiten. Die Daten werden in einem Store (Model) gespeichert.
Quellen
- Kowarschick (WebProg): Wolfgang Kowarschick; Vorlesung „Web-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2024; Quellengüte: 3 (Vorlesung)