HTML5-Tutorium: JavaScript: Hello World Vue 01
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 v01
(JavaScript)
Anwendungsfälle (Use Cases)
Gegenüber dem dritten, vierten, fünften und sechsten Teil des Tutoriums ändern sich die die Anwendungsfälle nicht. Die Anwendung leistet also genau dasselbe wie zuvor.
Aufgabe
In diesem Teil geht es zunächst darum, die Lösung aus Teil 6 des Tutoriums mit vue zu realisieren.
Erstellen eines neuen Projekts
Erstellen Sie ein neues Projekt hello_world_vue
:
cd <somewhere>
npm init vue@latest
Ok to proceed? (y)
Project name: » hello_world_vue
Add TypeScript? » No (Yes mittels Tab-Taste)
Add ESLint for code quality? » Yes
cd hello_world_vue
npm install
npm run dev # Im Browser: http://localhost:5173/
# Linefeed ändern (unter Windows => Unix-Zeilenende)
cat <<EOF > .vscode/settings.json
{ "files.eol": "\n" }
EOF
# VLC (neu) starten, damit settings.json gelesen wird
# und Terminal für das Projekt öffnen
# initialize git
git init
git add -A
git commit -m "initial commit"
git remote add origin https://gitlab.multimedia.hs-augsburg.de/ACCOUNT/hello_world_vue
git remote -v
git push --set-upstream origin master
# create a new git branch
git checkout -b v00
git push --set-upstream origin v00
Anmerkungen
Vue ist ein Framework zum Erstellen von Single-Page-Web-Anwendungen. Allerdings gibt es eine Router-Erweiterung: Multi-Page-Web-Anwendungen.
Vue basierte bis Version 3.0 auf Webpack. Webpack gilt allerdings schon wieder als Dinosaurier (existiert seit 2012)
Seit Version 3.2 verwendet Vue Vite (französisch „schnell“). Dies hat zur Konsequenz, dass das Initialisieren und Testen einer Vue-Anwendung anders erfolgt als früher.
Vue 3 unterstützt im Gegensatz zu Vue 2 TypeScript. Allerdings wir im Tutorium Typescript nicht eingesetzt.
Vue-Anwendungen sind aus Komponenten aufgebaut. Das passt sehr gut Atomic-Design-Prinzip.
Überführung von hello-world-06
nach vue
git checkout -b v01 # neuen Git-Zweig (branch) anlegen
npm i -D sass # sass aktivieren
.gitignore # ansehen
LICENSE # wird aus einem anderen Projekt kopiert
package.json # mit package.json von hello_world_06 mergen
vite.config.js # mit vite.config.js von hello_world_06 mergen
# Ausnahmen: root, publicDir, und outDir
index.html # gemäß hello_world_06 definieren; Import von 'main.js' npassen
src/css # Ordner von hello_world_06 übernehmen
public # favicon ersetzen
README.md # ansehen und verbessern
npm run dev # Vite-Server neu starten
Tipp
Wenn Sie Code von mir verwenden, sollten Sie in die Datei
eslintrc.cjs
nach Zeile 10 folgenden Code einfügen:
ignorePatterns:
[ 'dist', 'public'],
rules:
{ 'no-unexpected-multiline': 0 }
Relative Pfade
Um relative Pfade beim Building zu erzwingen, reicht es nicht, die Option base:
in vite.config.js einzufügen. Sie müssen dies zusätzlich in vue.config.js festlegen:
import { defineConfig } from '@vue/cli-service'
export default defineConfig ({ publicPath: '' })
Neuer Pfad-Alias
Um die SCSS-Konfigurationsdatei _config.scss
von jedem Ordner aus mittels
@import 'config';
importieren zu können, benötigt man einen weiteren Pfad-Alias-Eintrag in der Datei
vite.config.js
. Ergänzen Sie auch gleich einen Pfad für den Import von anderen CSS-Dateien.
resolve:
{ alias:
{ '@': fileURLToPath(new URL('./src', import.meta.url)),
'/css': fileURLToPath(new URL('./src/css', import.meta.url)),
'config': fileURLToPath(new URL('./src/css/_config.scss', import.meta.url)),
}
},
Definieren Sie auch noch eine Datei jsconfig.json
, mit der die Pfadverfolgung mittel Point an Click in Visual Studio Code ermöglicht wird.
Leider funktioniert dies nicht für den Alias config
.
{ "compilerOptions":
{ "baseUrl": ".",
"paths":
{ "@/*": ["./src/*"],
"/css/*": ["./src/css/*.scss"]
}
},
"exclude": [ "node_modules", "dist" ],
"extensions": [".js", ".vue", ".json"]
}
src/main.js
Da wir in diesem Tutorium die JavaScript-Dateien asynchron laden, müssen sie das Main-Skript entsprechenden anpassen. Die App darf erst erstellt und gemounted werden, wenn alle Dateien der App vollständig geladen wurden.
import { createApp } from 'vue'
import App from './App.vue'
window.addEventListener
( 'load',
() => createApp(App).mount('#app')
)
index.html
- Die Single-Page-Datei
index-html
wird gemäß Hello World 06 definiert.
Allerdings wird der Inhalt des Bodies in die Komponenten-Datei App.vue
verlagert.
Wenn Sie eine Datei favicon.ico
zur Hand haben, können Sie die Vite-Version dieser Datei ersetzen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name = "viewport"
content = "width=device-width, initial-scale=1.0, user-scalable=yes"
>
<link rel="icon" href="/favicon.ico">
<title>WK Hello World Vue 01</title>
<style>
@import url("src/css/head.css");
</style>
<script src="src/main.js" async="async" type="module"></script>
</head>
<body>
<main id="app"></main>
</body>
</html>
src/App.vue
- Die Hello-World-Komponente und das Style-Element laden.
- Nur die Hello-World-Komponente ins Template einfügen.
body.scss
importieren.
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<HelloWorld />
</template>
<style lang="scss">
@import '/css/body.scss';
</style>
Der Ordner src/assets
wird nun nicht mehr benötigt und kann gelöscht werden.
src/components/HelloWorld.vue
- Sections aus index.html in Template-Element einfügen.
- Sectionspezifische SCSS-Anweisungen in
src/css/HelloWorld.scss
verschieben und diese Datei insrc/components/HelloWorld.vue
importieren (import '/css/HelloWorld';
). - Skript-Element befüllen.
/* src/css/HelloWorld.scss */
#section_form
{ text-align: center;
margin-left: auto;
margin-right: auto;
h1
{ margin-bottom: 0.5ex;
margin-top: auto;
}
}
#section_hello
{ p
{ font-size: $font-size-p-large !important; }
}
<!-- src/components/HelloWorld.vue -->
<script setup>
import { ref, computed } from 'vue'
const
section = ref('question'),
helloStranger = ref('Hello, Stranger'),
name = ref(''),
hello = computed(() => `Hello, ${name.value}!`),
visability = p_section =>
p_section !== section.value ? 'hidden' : '',
sayHello = () => { section.value = 'hello' }
</script>
...
Hello-World-Komponente
Im Template von HelloWorld.vue sollten Sie alle Attribute "id"
mit Ausnahme von "section_question"
, "section_hello"
und "input_name"
löschen.
Der Grund ist, dass ID-Attribute im HTML-Dokument eindeutig sein müssen. Wenn in einer Komponente ein ID-Attribut definiert wird, kann man diese nicht mehrfach in eine andere Komponente einfügen.
Ein Ausnahme bildet das Attribut "input_name"
, da dieser Identifikator von zugehörigen laben referenziert wird: <label for="input_name">
. Bei der Erstellung einer eigenständigen Komponente Textfield muss man daher darauf achten, dass bei jeder Verwendung dieser Komponente ein neuer eindeutiger Identifikator (z. B. mittels uuid
) erzeugt wird. (Siehe Version v04.)
Außerdem benötig man diese ID in der Version v02 für den Enter-Key-Controller.
Darüber hinaus benötigen wir die Section-IDs für CSS. Diese werden erst später gelöscht.
<template>
<section id="section_question" v-bind:class="visability('question')">
<h1>{{helloStranger}}</h1>
<form>
<div>
<label for="input_name">What's your name?</label>
<input id="input_name" type="text" autofocus v-model="name" />
</div>
<div>
<input type="reset" value="Reset"/>
<input type="button" value="Say hello" v-on:click="sayHello" />
</div>
</form>
</section>
<section id="section_hello" v-bind:class="visability('hello')">
<h1>{{hello}}</h1>
<p>Welcome to Web Programming!</p>
</section>
</template>
...
Testen
Rufen Sie nun npm run dev
oder npm run build
sowie npm run prebuild
auf.
Alternative Skript-Varianten
<script setup>
(Vue 3.2)
<script setup>
import { ref, computed } from 'vue'
const
section = ref('question'),
helloStranger = ref('Hello, Stranger'),
name = ref(''),
hello = computed(() => `Hello, ${name.value}!`),
visability = p_section =>
p_section !== section.value ? 'hidden' : '',
sayHello = () => { section.value = 'hello' }
</script>
Composition API (Vue 3.0)
<script>
import { ref, computed } from 'vue'
export default
{ setup()
{ const
section = ref('question'),
helloStranger = ref('Hello, Stranger'),
name = ref(''),
hello = computed(() => `Hello, ${name.value}!`),
visability = p_section =>
p_section !== section.value ? 'hidden' : '',
sayHello = () => { section.value = 'hello' }
return {
section, helloStranger, name,
hello, visability, sayHello
}
}
}
</script>
Diese Variante kann ohne weitere Anpassungen an Stelle der Script-Setup-Variante verwendet werden. Allerdings ist die Script-Setup-Variante leichter zu schreiben und zu lesen.
Musterlösung wk_hello_world_vue, git checkout v01b
Options API (Vue 2.0)
<script>
export default
{ name: 'HelloWorld',
data:
function()
{ return {
section: 'question',
helloStranger: 'Hello, Stranger!',
name: ''
}
},
computed:
{ hello()
{ return `Hello, ${this.name}!` }
},
methods:
{ sayHello()
{ this.section = 'hello' },
visability(p_section)
{ return this.section !== p_section ? 'hidden' : '' }
}
}
</script>
Diese Variante kann ohne weitere Anpassungen an Stelle der Script-Setup-Variante verwendet werden. Allerdings ist die Script-Setup-Variante leichter zu schreiben und zu lesen. Die Options-API gilt als veraltet.
Musterlösung wk_hello_world_vue, git checkout v01c
Fortsetzung des Tutoriums
Sie sollten nun Teil 2 des Vue-Tutoriums bearbeiten. Es wird ein Keyup-Event-Handler ergänzt, zu Wahrung der Barrierefreiheit.
Quellen
- Kowarschick (WebProg): Wolfgang Kowarschick; Vorlesung „Web-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2024; Quellengüte: 3 (Vorlesung)