Frontend Development in 2024 - Gesamt
Inhalt
[[#vorwort|1 Vorwort 3]]
[[#das-setup|2 Das Setup 3]]
[[#git|2.1 Git 4]]
[[#repository|2.1.1 Repository 4]]
[[#commit|2.1.2 Commit 4]]
[[#branch|2.1.3 Branch 4]]
[[#merge|2.1.4 Merge 4]]
[[#konflikte|2.1.5 Konflikte 4]]
[[#staging-area|2.1.6 Staging Area 4]]
[[#remote-repository|2.1.7 Remote Repository 5]]
[[#pull-requests-pr-merge-requests-mr|2.1.8 Pull Requests (PR) / Merge Requests (MR) 5]]
[[#tags|2.1.9 Tags 5]]
[[#weiterführende-links|2.1.10 Weiterführende Links 5]]
[[#github|2.2 GitHub 5]]
[[#alles-beginnt-mit-einem-repo|2.2.1 Alles beginnt mit einem Repo 5]]
[[#github-und-projektmanagement|2.2.2 GitHub und Projektmanagement 7]]
[[#weiterführende-links-1|2.2.3 Weiterführende Links 7]]
[[#frontend-development-aber-richtig---integrierte-entwicklungsumgebungen|2.3 Frontend Development, aber richtig! - Integrierte Entwicklungsumgebungen 7]]
[[#visual-studio-code-vscode|2.3.1 Visual Studio Code (VSCode) 8]]
[[#fallbeispiel-from-peer-review-to-crowd-review|3 Fallbeispiel: From Peer Review to Crowd Review 11]]
[[#modernes-frontend-development|4 Modernes Frontend Development 12]]
[[#html-html5-für-die-strukturierung-von-webseiten|4.1 HTML, HTML5 für die Strukturierung von Webseiten 13]]
[[#css-css3-für-das-styling-von-webseiten|4.2 CSS, CSS3 für das Styling von Webseiten 14]]
[[#css-konstrukte|4.2.1 CSS-Konstrukte 14]]
[[#javascript-syntax-variablen-datentypen-und-operatoren|4.3 JavaScript-Syntax, Variablen, Datentypen und Operatoren 17]]
[[#variablen|4.3.1 Variablen 17]]
[[#datentypen|4.3.2 Datentypen 17]]
[[#operatoren|4.3.1 Operatoren 17]]
[[#funktionen|4.3.1 Funktionen 18]]
[[#kontrollstrukturen|4.3.2 Kontrollstrukturen 19]]
[[#objekte-und-arrays|4.3.3 Objekte und Arrays 19]]
[[#ereignisse|4.3.1 Ereignisse 20]]
[[#fehlerbehandlung|4.3.1 Fehlerbehandlung 20]]
[[#module|4.3.1 Module 21]]
[[#dom-dom-dom|5 DOM, DOM, DOM 21]]
[[#frameworks|6 Frameworks 30]]
[[#react|6.1 React 30]]
[[#komponenten|6.1.1 Komponenten 31]]
[[#jsx|6.1.2 JSX 31]]
[[#props|6.1.3 Props 31]]
[[#state|6.1.4 State 32]]
[[#lifecycle-methoden|6.1.5 Lifecycle-Methoden 32]]
[[#virtual-dom|6.1.6 Virtual DOM 33]]
[[#event-handling|6.1.7 Event-Handling 33]]
[[#hooks|6.1.8 Hooks 34]]
[[#erste-react-applikation-in-vscode|6.1.9 Erste React Applikation in VSCode 34]]
[[#angular|6.2 Angular 37]]
[[#komponenten-1|6.2.1 Komponenten 37]]
[[#module-1|6.2.2 Module 38]]
[[#services|6.2.3 Services 38]]
[[#routing|6.2.4 Routing 39]]
[[#datenbindung|6.2.5 Datenbindung 39]]
[[#forms|6.2.6 Forms 40]]
[[#dependency-injection|6.2.7 Dependency Injection 40]]
[[#mein-erstes-angular-projekt-in-vscode|6.2.8 Mein erstes Angular Projekt in VSCode 41]]
[[#verändere-die-app.component.html|6.2.9 Verändere die app.component.html 44]]
[[#vue.js|6.3 Vue.js 44]]
[[#komponenten-2|6.3.1 Komponenten 44]]
[[#reaktive-datenbindung|6.3.2 Reaktive Datenbindung 45]]
[[#props-1|6.3.3 Props 46]]
[[#event-handling-1|6.3.4 Event Handling 46]]
[[#vue-router|6.3.5 Vue Router 47]]
[[#vuex|6.3.6 Vuex 48]]
[[#mein-erstes-vue.js-projekt-in-vscode|6.3.7 Mein erstes Vue.js Projekt in VSCode 49]]
[[#asynchrone-programmierung-und-datenübertragung|7 Asynchrone Programmierung und Datenübertragung 52]]
[[#asyncawait|7.1 async/await 53]]
[[#api-definitionen|7.2 API Definitionen 56]]
[[#swagger-ui-verwenden|7.2.1 Swagger UI verwenden 56]]
[[#api-definition-für-unser-fallbeispiel|7.2.2 API Definition für unser Fallbeispiel 57]]
[[#alternative-tools|7.2.3 Alternative Tools 60]]
[[#responsive-webdesign|8 Responsive Webdesign 60]]
[[#gestaltung-von-benutzeroberflächen-die-auf-verschiedenen-geräten-und-bildschirmgrößen-gut-funktionieren|8.1 Gestaltung von Benutzeroberflächen, die auf verschiedenen Geräten und Bildschirmgrößen gut funktionieren 60]]
[[#responsive-layout|8.1.1 Responsive Layout 61]]
[[#media-queries|8.1.2 Media Queries 61]]
[[#flexible-bilder|8.1.3 Flexible Bilder 62]]
[[#touchfreundliche-elemente|8.1.4 Touchfreundliche Elemente 62]]
[[#testen|8.1.5 Testen 62]]
[[#medienabfragen-und-die-verwendung-von-css-frameworks-zur-unterstützung-des-responsiven-designs|8.2 Medienabfragen und die Verwendung von CSS-Frameworks zur Unterstützung des responsiven Designs 62]]
[[#medienabfragen|8.2.1 Medienabfragen 62]]
[[#verwendung-von-css-frameworks|8.2.2 Verwendung von CSS-Frameworks 63]]
[[#leistungsoptimierung|9 Leistungsoptimierung 64]]
[[#optimierung-von-ladezeiten|9.1 Optimierung von Ladezeiten 64]]
[[#lazy-loading|9.1.1 Lazy Loading 65]]
[[#caching|9.1.2 Caching 65]]
[[#minimierung-von-http-anfragen|9.1.3 Minimierung von HTTP-Anfragen 66]]
[[#komprimierung|9.1.4 Komprimierung 66]]
[[#optimierung-von-bildern|9.1.5 Optimierung von Bildern 66]]
[[#content-delivery-network-cdn|9.1.6 Content Delivery Network (CDN) 67]]
[[#ressourcenoptimierung|9.2 Ressourcenoptimierung 67]]
[[#code-splitting|9.2.1 Code-Splitting 67]]
[[#vermeidung-von-übermäßigem-dom-manipulationen|9.2.2 Vermeidung von übermäßigem DOM-Manipulationen 67]]
[[#minimierung-von-berechnungen-im-haupt-thread|9.2.3 Minimierung von Berechnungen im Haupt-Thread 68]]
[[#ressourcenoptimierung-durch-lazy-loading-von-bildern|9.2.4 Ressourcenoptimierung durch Lazy Loading von Bildern 68]]
[[#vermeidung-von-redundanz-bei-netzwerkanfragen|9.2.5 Vermeidung von Redundanz bei Netzwerkanfragen 68]]
[[#effiziente-datenabfragen|9.2.6 Effiziente Datenabfragen 69]]
[[#optimierung-der-bildgröße|9.2.7 Optimierung der Bildgröße 69]]
[[#_Toc174479597|10 Bibliography 69]]
Vorwort
Es ist 2024. Softwareentwicklung verändert sich gerade in einer Weise wie ich es seit meinem ersten Kontakt mit dieser Disziplin um das Jahr 2010 nicht erlebt habe. ChatBots und KI-gestützte Tools verändern, wie man Softwareprojekte angeht. OpenAIs ChatGPT (OpenAI, 2024) und GitHubs CoPilot (CoPilot, 2024) sind disruptive Technologien, die es Entwickler*innen ermöglichen sich mehr auf die Softwarearchitektur und das große Ganze zu konzentrieren und Unterstützung bei der Detailarbeit zu erhalten.
Eines bleibt, wie es immer war: Es gibt nur einen Weg, Programmieren zu lernen, und dieser heißt: selbst zu programmieren. Dieses Studienheft zu lesen, wird niemandem programmieren beibringen. Softwareentwicklung, egal mit welcher Programmiersprache, kann man nur durch Praxis erlernen und vertiefen. Was mich bei Lehrbüchern oft gestört hat, war, dass oft eine Sprache und deren Konzepte erklärt wurden, aber nicht, wie der ganze Prozess von Anfang bis zum Ende funktioniert. Deshalb beginnen wir in diesem Fach mit dem Setup und dem Tooling, welches für ein Frontendprojekt notwendig ist und in der Praxis verwendet wird.
Das Setup
Bevor wir uns mit JavaScript befassen, richten wir das Entwicklungssetup ein und lernen nützliche Werkzeuge kennen, die das Programmieren erleichtern. Ein lokal laufendes Programm ist zwar gut, kann aber meistens von niemand anderem einfach verwendet werden. Programmieren ist ein Teamsport. Deshalb beginnen wir mit Versionskontrollsystemen, GitHub und der Entwicklungsumgebung. Falls das alles bereits bekannt ist und bereits ein Frontend-Development-Setup vorhanden ist können die nächsten Kapitel überflogen werden und es kann mit der Erstellung des GitHub-Repositories begonnen werden.
Git
Git (git, 2024) ist ein Versionskontrollsystem (VCS), das die Verwaltung von Quellcode ermöglicht. Es speichert Änderungen an Dateien und erlaubt es, auf frühere Versionen zurückzugreifen. Zuerst gehen wir einige Begriffe durch, und danach werden wir es anwenden und ein GitHub-Repository erstellen. Selbst wenn man allein programmiert, bringt die Verwendung eines VCS Vorteile.
Repository
Ein Repository (Repo) ist ein Speicherort für den Quellcode eines Projekts. Es enthält alle Dateien und Verzeichnisse des Projekts sowie die gesamte Historie der Änderungen.
Lokal: Ein lokales Repository befindet sich auf deinem Computer.
Remote: Ein Remote-Repository befindet sich auf einem Server (z.B. GitHub (GitHub, 2024), GitLab (GitLab, 2024) oder BitBucket (BitBucket, 2024)).
Commit
Ein Commit ist eine gespeicherte Version des Projekts. Jeder Commit hat eine eindeutige ID und enthält eine Nachricht, die die vorgenommenen Änderungen beschreibt.
git commit -m "Beschreibung der Änderung"
Branch
Ein Branch ist ein unabhängiger Entwicklungszweig innerhalb des Repositories. Der Hauptbranch heißt meist main.
git branch <branch-name>
Merge
Merging kombiniert die Änderungen aus einem Branch mit einem anderen. Oft wird ein Feature-Branch in den Hauptbranch gemergt.
git merge <branch-name>
Konflikte
Konflikte entstehen, wenn Änderungen in verschiedenen Branches kollidieren. Git kann diese nicht automatisch zusammenführen, sodass eine manuelle Auflösung erforderlich ist.
Staging Area
Die Staging Area ist eine Zwischenschicht zwischen den Dateien im Arbeitsverzeichnis und dem Repository. Änderungen müssen zur Staging Area hinzugefügt werden, bevor sie committet werden.
git add <datei-name>
Remote Repository
Ein Remote-Repository ist eine gehostete Version eines Repositories.
- Push: Änderungen von lokal nach remote senden.
git push origin <branch-name>
- Pull: Änderungen von remote nach lokal holen.
git pull origin <branch-name>
Pull Requests (PR) / Merge Requests (MR)
Ein PR oder MR ist eine Anfrage zur Überprüfung und Integration von Änderungen von einem Branch in einen anderen. In der Praxis ist es üblich, dass ein PR von mehreren Entwicklern überprüft wird bevor dieser gemergt wird. In dieser Lehrveranstaltung muss immer ein PR für jede Änderung des Quellcodes erstellt werden.
Tags
Tags sind feste Referenzpunkte im Verlauf eines Projekts. Sie werden oft verwendet, um Versionen zu markieren (z.B. v1.0.0).
git tag <tag-name>
Weiterführende Links
GitHub
GitHub (GitHub, 2024) ist eine web-basierte Plattform, welche Git-Repositories hostet und zusätzliche Funktionen für die Zusammenarbeit und das Projektmanagement bietet. Es wird häufig von Entwicklern verwendet, um Quellcode zu speichern, zu verwalten und gemeinsam zu bearbeiten.
Alles beginnt mit einem Repo
Gehen wir das Gelernte nun an einem Beispiel durch. Die Erstellung eines Repos in einer der oben genannten Plattformen sollte immer der erste Schritt eines jeden Softwareprojekts sein. In dieser Lehrveranstaltung verwenden wir GitHub.
Bevor wir beginnen, schauen wir uns an wo wir hinwollen. Ein Repo sollte eine gute “README.md“ Datei haben, welche erklärt wie man das Projekt verwenden kann. .md steht dabei für Markdown (Markdown, 2024). Markdown ist ein Markup-Sprache, die zum Formatieren von Dokumenten verwendet wird. Hier ein paar Beispiele von gut strukturierten Repos und READMEs.
- https://github.com/facebook/react/blob/main/README.md
- https://github.com/angular/angular/blob/main/README.md
- https://github.com/vuejs/vue/blob/main/README.md
Gute READMEs enthalten eine Beschreibung, worum es bei dem Softwareprojekt geht, wie man es verwendet, wie man etwas beisteuern kann sowie Lizenzen. Erstellen wir nun ein GitHub Konto und erstellen ein erstes Repo. Falls git noch nicht installiert ist, können wir dieser Anleitung folgen: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git.
Konto erstellen:
- Gehe zu GitHub und erstelle ein Konto
Ein Repository erstellen:
- Klicke auf "New" (Neu) oben rechts auf der GitHub-Website
- Gib einen Repository-Namen ein, wähle die Sichtbarkeit (öffentlich oder privat) und füge eine kurze Beschreibung hinzu
- Klicke auf "Create repository"
Git-Repository clonen:
- Öffne die Git-Bash (unter Windows) oder das Terminal (unter macOS/Linux)
- Klone das Repository von GitHub auf deinen lokalen Computer
git clone <Repository-URL>
Ersetze <Repository-URL> durch die URL des erstellten Repositories, welches auf GitHub zu finden ist.
Dateien hinzufügen und committen:
- Navigiere in das geklonte Verzeichnis:
cd <repository-name>
- Erstelle eine Datei in dem Verzeichnis und füge die Datei dann zur Staging Area hinzu (beispielsweise eine leere README.md Datei).
git add <datei-name>
- Commite die Änderungen:
git commit -m „Mein erster Commit“
Änderungen pushen:
- Sende deine Commits zum Remote-Repository auf GitHub:
git push origin <branch-name>
Ersetze <branch-name> durch den Namen deines Branches (z.B. main).
Pull Requests erstellen:
Wenn man an einem Projekt mit anderen arbeitest, können folgendermaßen Pull Requests (PR) erstellt werden, um Änderungen vorzuschlagen:
- Gehe auf GitHub zu deinem Repository
- Klicke auf "Pull requests" und dann auf "New pull request"
- Vergleiche die Änderungen und füge eine Beschreibung hinzu
- Klicke auf "Create pull request"
- Nachdem man einen Pull Request erstellt hast kann dieser gemergt werden
GitHub und Projektmanagement
GitHub und ähnliche Plattformen geben Entwicklern auch die Möglichkeit Tickets für Teilaufgaben Projektpläne zu erstellen.
Weiterführende Links
- GitHub Guides: Offizielle Tutorials und Ressourcen von GitHub
- Understanding the GitHub flow: Den GitHub-Workflow verstehen
Frontend Development, aber richtig! - Integrierte Entwicklungsumgebungen
IDEs (Integrated Development Environments) sind umfassende Softwareanwendungen, die Entwicklern Werkzeuge zur Verfügung stellen, um Software zu entwickeln, zu debuggen und zu verwalten. Sie bieten eine integrierte Umgebung, die Folgendes umfasst:
Code Editor: Ein Editor für die Erstellung und Bearbeitung von Quellcode in verschiedenen Programmiersprachen mit Funktionen wie Syntaxhervorhebung und Autovervollständigung.
Build Automation: Tools zur Automatisierung von Build-Prozessen, die das Kompilieren von Code und das Erstellen von ausführbaren Anwendungen erleichtern.
Debugger: Ein Debugger, der Entwicklern hilft, Fehler im Code zu identifizieren, zu überprüfen und zu beheben.
Version Control Integration: Integration mit Versionskontrollsystemen wie Git, um Codeänderungen zu verwalten und zu synchronisieren.
Projektmanagement: Funktionen zur Organisation und Verwaltung von Projekten, einschließlich Datei- und Ordnerstrukturen, Abhängigkeitsverwaltung und Projektvorlagen.
Code Refactoring: Werkzeuge zur Optimierung und Umstrukturierung des Codes, um ihn lesbarer, effizienter und wartbarer zu machen.
Plugin-Unterstützung: Die Möglichkeit, Funktionalitäten durch Plugins oder Erweiterungen zu erweitern, die spezielle Anforderungen oder Integrationen bieten können.
Beispiele für populäre IDEs sind:
- Visual Studio Code (Microsoft, 2024): Eine leichte und leistungsstarke Code-Editor-IDE von Microsoft, die eine Vielzahl von Sprachen und Plattformen unterstützt.
- IntelliJ IDEA (JetBrains, 2024): Eine Java-IDE von JetBrains, die auch Unterstützung für andere Sprachen bietet und für ihre intelligenten Code-Refactoring-Funktionen bekannt ist.
- Eclipse (Eclipse Foundation, 2024): Eine plattformübergreifende IDE, die ursprünglich für Java entwickelt wurde, aber durch Plugins erweitert werden kann, um andere Sprachen zu unterstützen.
Diese IDEs erleichtern Entwicklern das Arbeiten, indem sie eine zentrale und effiziente Umgebung bieten, um Code zu schreiben, zu testen und zu verwalten.
Visual Studio Code (VSCode)
Entwickler haben oft Präferenzen, wenn es darum geht, welche IDE am intuitivsten ist. Wir werden die Beispiele anhand von VSCode durchgehen.
Visual Studio Code herunterladen und installieren
Download: Gehe zur VSCode-Website und lade die Installationsdatei für dein Betriebssystem herunter.
Installation:
- Unter Windows: Öffne die heruntergeladene Datei und folge den Installationsanweisungen
- Unter MacOS: Ziehe die heruntergeladene VSCode-App in deinen Applications-Ordner.
- Unter Linux: Installiere VSCode über den Paketmanager deiner Distribution.
Erweiterungen installieren
Man muss sich das Leben nicht zu schwer machen. Es gibt viele nützliche Erweiterungen, die dabei helfen lesbaren, korrekten und effizienten Programmiercode zu schreiben.
Öffne VSCode nach der Installation, um einige nützliche Erweiterungen zu installieren.
Gehe zum "Extensions"-Tab (Symbol auf der linken Seitenleiste) und suche nach den folgenden Erweiterungen:
- ESLint (OpenJS Foundation, 2024): Ein Linter für JavaScript, der Syntaxfehler und Best Practices prüft.
- Prettier - Code formatter (Prettier, 2024): Ein Tool zur automatischen Codeformatierung.
Klicke auf "Install", um die Erweiterungen hinzuzufügen.
Hello, World
Erstelle nun einen neuen Ordner auf deinem Computer, um deine JavaScript-Datei zu speichern. Zum Beispiel: hello-world-js.
- Öffne VS Code
- Gehe zu Datei > Ordner öffnen.. und wähle das zuvor erstellte Verzeichnis hello-world-js aus
- Klicke im Explorer-Fenster von VS Code (links) auf das Symbol Neue Datei.
- Nenne die Datei index.html
- Füge den folgenden HTML-Code in die index.html Datei ein
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<metaname="viewport"content="width=device-width, initial-scale=1.0">
<title>Hello World</title>
</head>
<body>
<h1>Hello World</h1>
<script>
// JavaScript Code
console.log('Hello, World!');
</script>
</body>
</html>
- Speichere die index.html Datei (Strg+S oder Datei > Speichern)
- Navigiere zu deinem Projektverzeichnis und öffne die index.html Datei mit einem Webbrowser (z.B. Chrome, Firefox, Safari)
- Öffne die Entwicklerwerkzeuge des Browsers. In Chrome und Firefox kann man dies mit der rechten Maustaste auf der Seite tun und dann auf „Untersuchen“ oder „Element untersuchen“klicken
- Gehe zum Tab „Konsole”
„Hello, World!“ sollte in der Konsole zu sehen sein
Weiterführende Links
Fallbeispiel: From Peer Review to Crowd Review
Wir werden die Frontend Development und JavaScript Konzepte anhand eines Fallbeispiels durchgehen. Dieses Beispiel wird sich durch den gesamten Kurs ziehen und die Konzepte werden daran veranschaulicht.
Der Peer-Review-Prozess ist entscheidend für die Qualitätssicherung wissenschaftlicher Publikationen. Autoren reichen Manuskripte bei Zeitschriften ein, wo es zunächst von Editoren geprüft wird. Wenn es thematisch und formal passt, wird es an Experten (Gutachter) weitergeleitet. Diese bewerten die Arbeit hinsichtlich ihrer methodischen Korrektheit, Bedeutung, Originalität und Klarheit und erstellen Gutachten mit Empfehlungen zur Akzeptanz, Überarbeitung oder Ablehnung. Die Autoren erhält Feedback, überarbeiten das Manuskript gegebenenfalls und reichen es erneut ein. Nach mehreren Runden von Überarbeitungen und Begutachtungen treffen die Editoren eine endgültige Entscheidung, und die Arbeit wird veröffentlicht. Dieser Prozess ist doppel-blind oder doppel-anonym. Dies bedeutet, dass sowohl die Autoren als auch die Gutachter anonym bleiben. Weder die Autoren wissen, wer die Gutachter sind, noch wissen die Gutachter, wer die Autoren sind. Dies soll sicherstellen, dass die Bewertung der Arbeit objektiv und frei von Vorurteilen erfolgt.
Dieser Prozess hat mehrere Probleme. Gutachter können unbewusst voreingenommen sein, was zu unfairen Bewertungen führt. Die Anonymität der Begutachtungen kann Verantwortlichkeit verringern und Interessenkonflikte verschleiern. Der Prozess ist oft zeitaufwendig, was die Veröffentlichung verzögert, und die Qualität der Gutachten kann stark variieren. Gutachter sind häufig überlastet, was die Schnelligkeit und Qualität der Begutachtungen beeinträchtigten kann. Zudem besteht ein Publikationsbias zugunsten positiver Ergebnisse, und die hohen Kosten traditioneller Zeitschriften schränken den Zugang zu Forschungsergebnissen ein.
Ein Beispiel, welches ich gerne zur Veranschaulichung bringe, ist der Fall von drei MIT-Studenten, die 2015 erfolgreich gefälschte Forschungspapiere bei wissenschaftlichen Zeitschriften einreichten. Diese Papiere, die methodische Fehler und wissenschaftlich unsinnige Inhalte enthielten, wurden von den Gutachtern akzeptiert. Lest euch das Beispiel durch: https://news.mit.edu/2015/how-three-mit-students-fooled-scientific-journals-0414
Stellen wir uns also folgende Anwendung vor: Ein webbasiertes System zur transparenten Veröffentlichung, Begutachtung und Diskussion wissenschaftlicher Publikationen. Sie bietet eine Plattform, auf der Autoren ihre Forschungsarbeiten einreichen, Gutachter diese begutachten und Leser über die veröffentlichten Arbeiten diskutieren können. Der Prozess ist durch verschiedene Rollen (Autor, Gutachter, Leser) und klare Workflow-Schritte strukturiert.
In so einem System könnte man sich folgendes Datenmodell vorstellen:
Benutzer: Enthält alle Benutzer des Systems und speichert deren Informationen wie Benutzername, E-Mail, Passwort (gehasht) und Rolle (Autor, Gutachter, Leser) ab.
Publikationen: Speichert Informationen zu den wissenschaftlichen Publikationen wie Titel, Abstract, Inhalt, Autor und den aktuellen Status der Veröffentlichung ab.
Gutachten: Enthält die Gutachten, die von Gutachtern verfasst wurden, und Empfehlung (Akzeptieren, Kleine Überarbeitung, Große Überarbeitung, Ablehnen).
Kommentare: Ermöglicht Diskussionen und Kommentare zu den Publikationen durch verschiedene Benutzer.
GutachterZuweisungen: Verknüpft Gutachter mit den Publikationen, die sie bewerten sollen.
Wir werden in diesem Studienheft Schritt für Schritt die Benutzeroberfläche einer solcher Anwendung erstellen und optimieren.
Modernes Frontend Development
Beim Start eines Frontend-Projekts beginnt man mit dem Einrichten der Entwicklungsumgebung. Visual Studio Code wird installiert und konfiguriert, um eine effiziente Programmierumgebung zu bieten. Ein GitHub-Repository wird erstellt, um Versionskontrolle zu nutzen, und auf den lokalen Rechner geklont. Das Projekt wird in VSCode geöffnet und es werden hilfreiche Erweiterungen installiert.
Der nächste Schritt ist die Planung der Benutzeroberfläche. Wireframes und Mockups werden erstellt, um die Hauptbildschirme der Anwendung zu skizzieren, wie die Startseite, Publikationsübersicht und Detailansichten. Design-Tools wie Figma (Figma, 2024) werden verwendet, um die Benutzeroberflächen und deren Interaktionen detailliert zu entwerfen.
Für die Application Programming Interface (API)-Definition (auf Deutsch Programmierschnittstelle) werden die benötigten Endpunkte festgelegt, die zur Kommunikation mit dem Server genutzt werden. Eine API-Spezifikation kann beispielsweise mit OpenAPI (OpenAPI, 2024) erstellt werden, die die Endpunkte, Parameter und Rückgabewerte beschreibt. Diese Spezifikation wird in Tools wie Swagger UI (Swagger, 2024) geladen, um eine interaktive Dokumentation zu erstellen und die API zu testen.
Abschließend wird ein Frontend-Framework ausgewählt, das den Anforderungen entspricht. Beliebte Optionen wie React (Meta Open Source, 2024), Angular (Google, 2024) oder Vue.js (You, 2024) bieten umfassende Funktionalitäten zur Unterstützung der Anwendung. Das gewählte Framework wird eingerichtet, indem ein neues Projekt erstellt und konfiguriert wird, um die Entwicklungsarbeit zu beginnen.
JavaScript wird oft geschätzt, weil es vielseitig und zentral für die Webentwicklung ist, mit vielen nützlichen Bibliotheken und ständiger Weiterentwicklung. Die Sprache wird jedoch auch kritisiert wegen seiner Inkonsistenzen, untypisierten Natur und Sicherheitsproblemen, sowie wegen der Komplexität der zahlreichen Frameworks und Tools.
HTML5, CSS3 und JavaScript arbeiten zusammen, um moderne Webseiten zu gestalten. HTML5 definiert die grundlegende Struktur und den Inhalt der Webseite. CSS3 kümmert sich um das visuelle Design und Layout, wie Farben, Schriftarten und Abstände. JavaScript ermöglicht interaktive und dynamische Funktionen, indem es auf Benutzeraktionen reagiert und Inhalte in Echtzeit aktualisiert. Zusammen bieten diese Technologien die Basis für ansprechende und funktionale Webanwendungen.
Dies wäre kein vollständiges Frontend Development Studienheft ohne die Erwähnung von TypeScript (Microsoft, 2024). Wir werden uns auf JavaScript konzentrieren, in der Praxis wird jedoch oft TypeScript anstelle von JavaScript verwendet. Einer der größten Kritikpunkte von JavaScript ist, wie oben erwähnt, die untypisierte Natur. Ein kurzer Ausflug: In untypisierten Sprachen wie JavaScript können Variablen Werte unterschiedlichen Typs annehmen, und Typprüfungen erfolgen erst zur Laufzeit. Das bedeutet, dass Variablen flexibel sind, aber Typfehler erst beim Ausführen des Programms entdeckt werden können. In typisierten Sprachen wie TypeScript, Java oder C#, müssen Typen bereits zur Entwicklungszeit festgelegt werden, was eine frühzeitige Fehlererkennung und strukturierteren Code ermöglicht. Diese Sprachen überprüfen die Typen entweder zur Kompilierzeit oder bei der Programmausführung, was zu robusterem und weniger fehleranfälligem Code führt. Weitere untypisierte Sprachen sind Python, Ruby, PHP und Perl.
TypeScript ist eine Erweiterung von JavaScript, die statische Typisierung bietet, wodurch viele Fehler bereits zur Entwicklungszeit erkannt werden können. JavaScript ist flexibler und wird direkt von Browsern ausgeführt, erfordert jedoch Laufzeitprüfungen für Typfehler. TypeScript bietet zusätzliche Funktionen und eine robustere Entwicklungsumgebung, während JavaScript aufgrund seiner Flexibilität und breiten Unterstützung bevorzugt wird.
HTML, HTML5 für die Strukturierung von Webseiten
HTML (Hypertext Markup Language) und HTML5 sind beide Markup-Sprachen zur Strukturierung von Webseiten. HTML5 bringt einige Verbesserungen gegenüber HTML mit sich.
HTML ist die grundlegende Sprache für die Erstellung von Webseiten und definiert, wie Inhalte wie Texte, Links, Bilder und Listen strukturiert werden. Es bietet grundlegende Elemente, die es ermöglichen, einfache und funktionale Webseiten zu erstellen.
Elemente sind beispielsweise:
- <h1> bis <h6> für Überschriften
- <p> für Absätze
- <a> für Hyperlinks
- <img> für Bilder
HTML5 ist die neuere Version von HTML und baut auf HTML auf. Es bietet neue semantische Tags wie <header>, <footer>, <section>, und <article>, die helfen, Webseiten besser zu strukturieren und den Inhalt klarer zu gliedern. HTML5 unterstützt auch erweiterte Multimedia-Elemente wie <video> und <audio>, die es einfacher machen, Medieninhalte ohne zusätzliche Plugins einzubinden. Zudem bringt es Verbesserungen bei der Formularverarbeitung und der Unterstützung für moderne Webanwendungen, einschließlich APIs für lokale Speicherung und grafische Darstellungen.
Heutzutage ist HTML5 der Standard für die Webentwicklung.
Viel genützte Tags sind:
- <header>: Definiert den Kopfbereich einer Seite oder eines Abschnitts
- <nav>: Navigationslinks
- <section>: Markiert thematische Abschnitte innerhalb des Dokuments
- <article>: Stellt eigenständige Inhalte dar, die unabhängig wiederverwendet werden können
- <footer>: Gibt den Fußbereich einer Seite oder eines Abschnitts an
- <aside>: Definiert Inhalte, die nicht direkt zum Hauptinhalt gehören (z.B. Seitenleisten)
- <main>: Markiert den Hauptinhalt der Seite
- <figure> und <figcaption>: Dienen zur Darstellung von Bildern und zugehörigen Beschreibungen
- <video>: Einbetten von Videos
- <audio>: Einbetten von Audiodateien
- <progress>: Zeigt den Fortschritt eines laufenden Prozesses an.
In unserem Beispiel von oben haben wir einige dieser Tags verwendet. Nun fügen wir etwas CSS5 hinzu.
CSS, CSS3 für das Styling von Webseiten
CSS (Cascading Style Sheets) ist die grundlegende Styling-Sprache für Webseiten. CSS3 ist die aktuelle Version, die erweiterte Funktionen für modernes Layout und Design bietet.
CSS-Konstrukte
Selektoren: Bestimmen, welche HTML-Elemente gestaltet werden. Beispiel: p für alle Absätze, .class für Elemente mit der Klasse „class“, #id für das Element mit der ID „id“
Eigenschaften: Definieren, welche Stile angewendet werden. Beispiel: „color“ für die Textfarbe, „font-size“ für die Schriftgröße
Werte: Geben die spezifischen Einstellungen für die Eigenschaften an. Beispiel: „color: red“; für rote Textfarbe, „font-size: 16px;“ für eine Schriftgröße von 16 Pixel
Box-Modell: Beschreibt das Layout von Elementen.
Beispiele:
- „margin: 10px“, für den äußeren Abstand
- „border: 1px solid black“ für einen schwarzen Rand, padding: 5px; für den inneren Abstand, width: 100px; für die Breite des Inhaltsbereichs
Positionierung: Bestimmt, wie Elemente auf der Seite angeordnet werden. Beispiel: “position: relative;“ für relative Positionierung, „position: absolute;“ für absolute Positionierung, „top: 10px; left: 20px;“ für die Platzierung des Elements.
CSS3 führt eine Reihe neuer Konstrukte und Module ein, die das Design und Layout von Webseiten erweitern:
Flexbox: Ein Layout-Modul für flexible und anpassungsfähige Layouts. Beispiel: display: flex; auf einem Container, um dessen Kinder flexibel zu gestalten.
Grid Layout: Ermöglicht komplexe, zweidimensionale Layouts mit Zeilen und Spalten. Beispiel: display: grid;für ein Gitter-Layout.
Media Queries: Passen das Design je nach Bildschirmgröße oder Gerätetyp an. Beispiel: @media (max-width: 600px) { /* Styles für kleine Bildschirme */ }.
Animationen und Übergänge: Erlauben das Erstellen von dynamischen Effekten. Beispiel: @keyframes für Animationen und transition: all 0.3s ease; für sanfte Übergänge zwischen Zuständen.
Transform: Ermöglicht das Skalieren, Drehen oder Verschieben von Elementen. Beispiel: transform: rotate(45deg); zum Drehen eines Elements.
Gradienten: Erstellen von Farbverläufen. Beispiel: background: linear-gradient(to right, red, yellow);für einen Verlauf von Rot nach Gelb.
Hier das oben erwähnte Beispiel etwas aufgehübscht. Öffnen wir das Beispiel nun wieder in einem Browser und sehen es uns an.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>From Peer Review to Crowd Review</title>
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(to right, #342fc9, #2da327);
color: #333;
text-align: center;
margin: 0;
padding: 0;
}
h1 {
color: #007bff;
font-size: 3em;
margin-top: 20vh;
transition: color 0.3s ease;
}
h1:hover {
color: #0056b3;
transform: scale(1.1);
}
</style>
</head>
<body>
<h1> From Peer Review to Crowd Review </h1>
<script>
// JavaScript Code
console.log('Hello World!');
</script>
</body>
</html>
- CSS3 wurde im <style>-Tag hinzugefügt
- Der Hintergrund der Seite verwendet einen linearen Farbverlauf.
- Der Text der Überschrift <h1> erhält eine Farbe und eine Schriftgröße, und eine Übergangsanimation wird hinzugefügt, die beim Hover-Effekt die Farbe ändert und den Text leicht vergrößert.
JavaScript-Syntax, Variablen, Datentypen und Operatoren
Sehen wir uns nun die einzelnen Konstrukte der Sprache JavaScript genauer an.
Variablen
Deklaration: Variablen sind Container zum Speichern von Datenwerten. In JavaScript können sie mit den Schlüsselwörtern var, let und const deklariert werden.
- var: Wird verwendet, um eine Variable mit Funktions-Scope zu deklarieren. Variablen, die mit var deklariert wurden, können innerhalb ihrer Funktion neu deklariert und aktualisiert werden.
- let: Wird verwendet, um eine Variable mit Block-Scope zu deklarieren. Variablen, die mit let deklariert wurden, können innerhalb ihres Blocks aktualisiert, aber nicht neu deklariert werden.
- const: Wird verwendet, um eine Konstante zu deklarieren, die nicht neu zugewiesen werden kann. Konstanten haben ebenfalls Block-Scope.
var alterBenutzername = 'neo_the_one';
let benutzername = 'alice_wonderland';
const email = 'alice@example.com';
let rolle = 'Autor';
Datentypen
Primitive Typen: Dazu gehören Number, String, Boolean, Null, Undefined und Symbol.
Komplexe Typen: Dazu gehören Objekte und Arrays.
Beispiele für primitive Typen sind:
Number:
let zahl = 42;
String:
let text = "Hello World";
Boolean:
let wahrOderFalsch = true;
Null:
let leererWert = null;
Undefined:
let undefiniert;
Symbol:
let symbol = Symbol("einzigartig");
Operatoren
Vergleichsoperatoren: Werden verwendet, um zwei Werte zu vergleichen. Die gängigen Vergleichsoperatoren sind ==, ===, !=, !==, <, >, <=, >=.
Gleich (==): Vergleicht zwei Werte, wobei Typkonvertierungen durchgeführt werden, wenn nötig. Beispiel: 42 == '42'ergibt true, weil '5' zu 5 konvertiert wird.
Strikte Gleichheit (===): Vergleicht zwei Werte ohne Typkonvertierungen. Beide Werte müssen denselben Typ und Wert haben. Beispiel: 42 === '42' ergibt false, da die Typen unterschiedlich sind.
Ungleich (!=): Vergleicht zwei Werte, wobei Typkonvertierungen durchgeführt werden, wenn nötig. Beispiel: 42 != '42'ergibt false, da '42' zu 42 konvertiert wird.
Strikte Ungleichheit (!==): Vergleicht zwei Werte ohne Typkonvertierungen. Beide Werte müssen entweder im Typ oder im Wert unterschiedlich sein. Beispiel: 42 !== '42' ergibt true, da die Typen unterschiedlich sind.
Größer als (>): Überprüft, ob der linke Wert größer als der rechte Wert ist. Beispiel: 42 > 23 ergibt true.
Kleiner als (<): Überprüft, ob der linke Wert kleiner als der rechte Wert ist. Beispiel: 23 < 42 ergibt true.
Größer oder gleich (>=): Überprüft, ob der linke Wert größer oder gleich dem rechten Wert ist. Beispiel: 42 >= 42 ergibt true, und 42 >= 23 ergibt true.
Kleiner oder gleich (<=): Überprüft, ob der linke Wert kleiner oder gleich dem rechten Wert ist. Beispiel: 23 <= 42 ergibt true, und 42 <= 42 ergibt true.
In unserem Fallbeispiel könnten wir Operatoren beispielsweise folgendermaßen verwenden:
if (publikation.status === 'eingereicht') {
console.log('Die Publikation wurde eingereicht und wartet auf Begutachtung.');
}
Funktionen
Funktion: Ein Block von Code, der entworfen wurde, um eine bestimmte Aufgabe auszuführen. Funktionen können Parameter (Eingaben) annehmen und ein Ergebnis zurückgeben.
function neuerBenutzer(benutzername, email, passwort, rolle) {
return {
benutzername: benutzername,
email: email,
passwort: passwort,
rolle: rolle
};
}
let neuerAutor = neuerBenutzer('neo_the_one', 'neo@example.com', 'hashed_password2', 'Autor');
Kontrollstrukturen
Bedingte Anweisungen: Dazu gehören if, else if und else, die verwendet werden, um Code basierend auf spezifischen Bedingungen auszuführen.
Schleifen: Dazu gehören for, while und do...while, die verwendet werden, um Codeblöcke wiederholt auszuführen.
if (neuerAutor.rolle === 'Autor') {
console.log('Willkommen, Autor!');
}
let gutachtenListe = [
{ empfehlung: 'Akzeptieren', kommentar: 'Sehr gute Arbeit.' },
{ empfehlung: 'Kleine Überarbeitung', kommentar: 'Einige kleine Korrekturen erforderlich.' }
];
for (let i = 0; i < gutachtenListe.length; i++) {
console.log(gutachtenListe[i].empfehlung);
}
Objekte und Arrays
Objekte: Sammlungen von Schlüssel-Wert-Paaren, wobei die Schlüssel Zeichenketten oder Symbole und die Werte beliebige Datentypen sein können.
Arrays: Geordnete Listen von Werten, auf die über ihren Index zugegriffen wird.
Beispiel einen Objektes:
let kommentar = {
benutzername: 'neo_the_one',
kommentar: 'Sehr interessante Publikation!',
datum: '2024-08-10'
};
Beispiel eines Arrays:
let wissenschaftlichePublikationen = ["Deep Learning in AI", "Quantum Computing Advances", "Blockchain Technology Overview", "Genomics and CRISPR", "Sustainable Energy Solutions"];
In JavaScript greift man auf einzelne Elemente folgendermaßen zu:
let erstePublikation = wissenschaftlichePublikationen[0];
In diesem Fall ist erstePublikation gleich "Deep Learning in AI".
JavaScript-Arrays sind etwas flexibler als Arrays in anderen Programmiersprachen. Sie sind dynamisch und können wachsen oder schrumpfen, ohne eine feste Größe zu haben. Sie erlauben auch das Speichern von Elementen unterschiedlicher Typen, wie Zahlen, Strings und Objekte. Das macht sie flexibler im Vergleich zu Arrays in Sprachen wie Java, die eine feste Größe haben und nur Elemente eines einzigen Datentyps enthalten können. Zudem bieten JavaScript-Arrays zahlreiche eingebaute Methoden zur Manipulation von Daten, wie push, pop und shift, was sie vielseitiger und einfacher zu handhaben macht.
Ereignisse
Ereignis: Eine Aktion welche im System erkannt und darauf reagiert wird. Beispiele sind Mausklicks, Tastatureingaben oder das Laden einer Seite.
Mausklick:
document.getElementById("zeigePublikation").addEventListener("click", function() {
alert("Publikation: Deep Learning in AI");
});
Mouseover (Maus über ein Element bewegen):
document.getElementById("zeigePublikation").addEventListener("mouseover", function() {
console.log("Maus ist über dem Publikationsbereich!");
});
Keydown (Tastendruck):
document.addEventListener("keydown", function(event) {
console.log("Gedrückte Taste: " + event.key);
});
Seitenladen (DOMContentLoaded):
document.addEventListener("DOMContentLoaded", function() {
console.log("Die Seite ist vollständig geladen!");
});
Formular absenden:
document.getElementById("publikationsFormular").addEventListener("submit", function(event) {
event.preventDefault(); // Verhindert das Standardverhalten
alert("Formular zur Publikation wurde abgesendet!");
});
Fehlerbehandlung
Fehlerbehandlung: Verwendung von try, catch, finally und throw, um Fehler zu erkennen und zu verarbeiten.
try {
let neuerGutachter = neuerBenutzer('alice_wonderland', 'alice@example.com', 'hashed_password3', 'Gutachter');
if (!neuerGutachter.email.includes('@')) {
throw new Error('Ungültige E-Mail-Adresse');
}
} catch (error) {
console.log(error.message);
}
Module
Module: Erlauben es, Code in separate Dateien zu unterteilen. Jedes Modul kann Werte oder Funktionen exportieren und in anderen Dateien importieren.
// benutzer.js
export function neuerBenutzer(benutzername, email, passwort, rolle) {
return {
benutzername: benutzername,
email: email,
passwort: passwort,
rolle: rolle
};
}
// main.js
import { neuerBenutzer } from './benutzer.js';
let neuerLeser = neuerBenutzer('neo_the_one', 'neo@example.com', 'hashed_password4', 'Leser');
console.log(neuerLeser);
DOM, DOM, DOM
Der Document Object Model (DOM) ist eine Programmierschnittstelle für HTML- und XML-Dokumente. Es repräsentiert die Struktur eines Dokuments als eine Baumstruktur, wobei jede HTML- oder XML-Komponente (wie Tags, Attribute und Text) als Knoten dargestellt wird. Mit dem DOM können Sie die Struktur, den Inhalt und das Styling eines Dokuments dynamisch ändern.
Kommen wir zurück zu unserem Fallbeispiel. Auf unserer Webseite möchten wir Informationen zu Publikationen anzeigen und es den Benutzern ermöglichen, Kommentare zu hinterlassen.
Ein einfaches HTML-Dokument für unser System könnte wie folgt aussehen:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Publikationen</title>
</head>
<body>
<h1>Wissenschaftliche Publikationen</h1>
<div id="publikation-container">
<h2 id="publikation-titel">Gibt es die Matrix wirklich?</h2>
<p id="publikation-abstract">Eine umfassende Analyse der Frage, ob wir in einer simulierten Realität leben.</p>
<div id="kommentare">
<h3>Kommentare</h3>
<!-- Kommentare werden hier hinzugefügt -->
</div>
<textarea id="neuer-kommentar" placeholder="Fügen Sie einen Kommentar hinzu..."></textarea>
<button id="kommentar-hinzufuegen">Kommentar hinzufügen</button>
</div>
<script src="app.js"></script>
</body>
</html>
In diesem Beispiel haben wir HTML-Elemente wie h1, h2, p, div, textarea und button, die verschiedene Teile unserer Publikationsseite darstellen. Das DOM repräsentiert diese Elemente als Knoten in einem Baum.
In unserem JavaScript-Code können wir auf diese DOM-Elemente zugreifen und sie manipulieren. Erstelle in demselben Ordner eine neue Datei app.js. In dieser Datei schreiben wir den JavaScript Code. Auf diesen wird in dem obigen Beispiel mit <script src=“app.js“> zugegriffen. Manipulieren wir nun die HTML Datei mit JavaScript code. Hier sind einige Beispiele:
// Zugriff auf DOM-Elemente
let titelElement = document.getElementById('publikation-titel');
let abstractElement = document.getElementById('publikation-abstract');
let kommentareElement = document.getElementById('kommentare');
let textareaElement = document.getElementById('neuer-kommentar');
let buttonElement = document.getElementById('kommentar-hinzufuegen');
// Hinzufügen eines Kommentars
buttonElement.addEventListener('click', () => {
let neuerKommentar = textareaElement.value;
if (neuerKommentar) {
let kommentarElement = document.createElement('p');
kommentarElement.textContent = neuerKommentar;
kommentareElement.appendChild(kommentarElement);
textareaElement.value = ; // Textarea leeren
} else {
alert('Bitte geben Sie einen Kommentar ein.');
}
});
Öffne die HTML Datei erneut in deinem Browser und siehe was sich verändert hat.
Im obigen JavaScript-Beispiel verwenden wir das DOM, um:
- Elemente zu finden: Wir greifen auf Elemente wie den Titel und das Abstract der Publikation zu.
- Ereignisse zu behandeln: Wir fügen einen Event-Listener für den Button hinzu, um einen Kommentar hinzuzufügen, wenn der Button geklickt wird.
- Elemente zu erstellen und zu modifizieren: Wir erstellen neue p-Elemente für Kommentare und fügen sie dem DOM hinzu. Außerdem ändern wir den Inhalt von textarea und leeren ihn nach dem Hinzufügen eines Kommentars.
Die Baumstruktur des DOM für unser Beispiel sieht folgendermaßen aus:
<html>
<head>
<meta>
<title>
<body>
<h1>
<div id="publikation-container">
<h2 id="publikation-titel">
<p id="publikation-abstract">
<div id="kommentare">
<h3>
(Kommentare werden hier hinzugefügt)
<textarea id="neuer-kommentar">
<button id="kommentar-hinzufuegen">
Sehen wir uns nun weitere Beispiele von Ereignissen an.
Ereignis: Eingabe in Textarea
Beschreibung: Zeigt eine Live-Vorschau des eingegebenen Kommentars an, während der Benutzer tippt.
// Zugriff auf DOM-Elemente
let textareaElement = document.getElementById('neuer-kommentar');
let liveVorschauElement = document.createElement('div');
liveVorschauElement.id = 'live-vorschau';
document.body.appendChild(liveVorschauElement);
// Ereignis-Handler für die Eingabe in die Textarea
textareaElement.addEventListener('input', () => {
let eingabeText = textareaElement.value;
liveVorschauElement.textContent = `Vorschau: ${eingabeText}`;
});
Ereignis: Mausbewegung
Beschreibung: Ändert die Hintergrundfarbe eines Elements, wenn die Maus darüber bewegt wird.
// Zugriff auf DOM-Element
let titelElement = document.getElementById('publikation-titel');
// Ereignis-Handler für Mausbewegung
titelElement.addEventListener('mouseover', () => {
titelElement.style.backgroundColor = '#f0f0f0'; // Hintergrundfarbe ändern
});
// Ereignis-Handler für Mausverlassen
titelElement.addEventListener('mouseout', () => {
titelElement.style.backgroundColor = ; // Hintergrundfarbe zurücksetzen
});
Ereignis: Formular-Submit
Beschreibung: Verhindert das Standard-Submit-Verhalten eines Formulars und zeigt stattdessen eine Bestätigungsmeldung an.
index.html
<form id="kommentar-form">
<textarea id="neuer-kommentar" placeholder="Fuegen Sie einen Kommentar hinzu...">
</textarea>
<button type="submit" id="kommentar-hinzufuegen">Kommentar hinzufuegen
</button>
</form>
<script src="app.js"></script>
app.js
// Zugriff auf DOM-Elemente
let textareaElement = document.getElementById('neuer-kommentar');
let formElement = document.getElementById('kommentar-form');
// Ereignis-Handler für Formular-Submit
formElement.addEventListener('submit', (event) => {
event.preventDefault(); // Verhindert das Standard-Submit-Verhalten
let neuerKommentar = textareaElement.value;
if (neuerKommentar) {
let kommentarElement = document.createElement('p');
kommentarElement.textContent = neuerKommentar;
textareaElement.value = ; // Textarea leeren
alert('Kommentar erfolgreich hinzugefuegt!');
} else {
alert('Bitte geben Sie einen Kommentar ein.');
}
});
Ereignis: Tastatureingabe
Beschreibung: Zeigt eine Nachricht an, wenn die Eingabetaste gedrückt wird.
// Ereignis-Handler für Tastatureingaben
document.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
alert('Eingabetaste wurde gedrückt!');
}
});
Ereignis: Ändern eines Select-Menüs
Beschreibung: Zeigt die ausgewählte Option aus einem Dropdown-Menü an, wenn der Benutzer eine Auswahl trifft.
<select id="rolle-select">
<option value="Autor">Autor</option>
<option value="Gutachter">Gutachter</option>
<option value="Leser">Leser</option>
</select>
<div id="ausgewaehlte-rolle"></div>
// Zugriff auf DOM-Elemente
let rolleSelectElement = document.getElementById('rolle-select');
let ausgewaehlteRolleElement = document.getElementById('ausgewaehlte-rolle');
// Ereignis-Handler für Änderungen des Select-Menüs
rolleSelectElement.addEventListener('change', () => {
let ausgewaehlteRolle = rolleSelectElement.value;
ausgewaehlteRolleElement.textContent = `Ausgewählte Rolle: ${ausgewaehlteRolle}`;
});
Frameworks
JavaScript-Frameworks erleichtern die Webentwicklung, indem sie strukturierte Ansätze, wiederverwendbare Komponenten und integrierte Funktionen bieten. Die meistverwendeten Frameworks sind React (Meta, 2024), Angular (Google, 2024) und Vue.js (You, 2024). React, von Facebook entwickelt, konzentriert sich auf die Erstellung von Benutzeroberflächen mit einem komponentenbasierten Modell und einem Virtual DOM für effiziente Updates. Angular, gepflegt von Google, bietet eine umfassende Lösung für große Webanwendungen, inklusive Dependency Injection und Routing, und verwendet TypeScript für statische Typisierung. Vue.js ist ein leichtgewichtiges Framework, das einfach zu integrieren und zu lernen ist, und bietet eine flexible API, die Elemente von React und Angular kombiniert. Die Wahl eines Frameworks hängt von den spezifischen Projektanforderungen ab. Diese Frameworks sparen Zeit, verbessern die Code-Qualität, optimieren die Leistung und bieten umfassende Dokumentation sowie Community-Support, was zu schnellerer, konsistenterer und wartbarer Entwicklung führt.
React
React ist eine JavaScript-Bibliothek, die es ermöglicht, komplexe Benutzeroberflächen in wiederverwendbare, isolierte Komponenten zu zerlegen. Diese Komponenten verwalten ihren eigenen Zustand und nutzen einen virtuellen DOM, um effizient Änderungen an der Benutzeroberfläche vorzunehmen. Dies führt zu einer reaktiven und schnellen Anwendung.
Komponenten
In React ist eine Komponente ein selbstständiges, wiederverwendbares Stück der Benutzeroberfläche. Sie kann in andere Komponenten eingebettet werden und hat ihren eigenen Zustand und ihre eigene Logik.
Beispiel: Für unsere Anwendung könnten wir eine Publikation-Komponente erstellen, die die Details einer wissenschaftlichen Publikation anzeigt.
function Publikation({ titel, abstract, inhalt }) {
return (
<div>
<h2>{titel}</h2>
<p>{abstract}</p>
<div>{inhalt}</div>
</div>
);
}
In diesem Beispiel ist Publikation eine Komponente, die titel, abstract und inhalt als Props erhält und diese Daten in der Benutzeroberfläche darstellt.
JSX
JSX ist eine Syntaxerweiterung für JavaScript, die es ermöglicht, HTML-ähnlichen Code direkt in JavaScript zu schreiben. Dieser Code wird von React in regulären JavaScript-Code übersetzt.
Beispiel: Das folgende JSX beschreibt die Struktur eines Kommentarformulars.
function KommentarFormular() {
return (
<form>
<textarea placeholder="Fügen Sie einen Kommentar hinzu..." />
<button type="submit">Kommentar hinzufügen</button>
</form>
);
}
Hier sehen wir, wie HTML-ähnlicher Code in JavaScript eingebettet wird, um die Benutzeroberfläche zu definieren.
Props
Props (Eigenschaften) sind Parameter, die an Komponenten übergeben werden, um Daten weiterzugeben. Sie sind unveränderlich innerhalb der Komponente.
Beispiel: In der App-Komponente übergeben wir Daten an die Publikation-Komponente.
function App() {
return (
<Publikation
titel="Gibt es die Matrix wirklich?"
abstract="Eine Untersuchung der Realität und ihrer Möglichkeiten."
inhalt="Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt."
/>
);
}
Hier erhält Publikation die Daten als Props und zeigt diese in der Benutzeroberfläche an.
State
Der State ist der interne Zustand einer Komponente, der sich ändern kann und die Darstellung der Komponente beeinflusst. Er ist veränderbar und ermöglicht es, die Benutzeroberfläche dynamisch zu aktualisieren.
Beispiel: In der KommentarFormular-Komponente verwalten wir den Text des Kommentars im State.
import React, { useState } from 'react';
function KommentarFormular() {
const [kommentar, setKommentar] = useState();
const handleChange = (event) => {
setKommentar(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
alert('Kommentar hinzugefügt: ' + kommentar);
setKommentar();
};
return (
<form onSubmit={handleSubmit}>
<textarea
value={kommentar}
onChange={handleChange}
placeholder="Fügen Sie einen Kommentar hinzu..."
/>
<button type="submit">Kommentar hinzufügen</button>
</form>
);
}
Hier verwenden wir den State, um den aktuellen Kommentar zu speichern und die Benutzeroberfläche bei Änderungen zu aktualisieren.
Lifecycle-Methoden
Lifecycle-Methoden sind spezielle Methoden, die zu verschiedenen Zeitpunkten im Lebenszyklus einer Komponente aufgerufen werden. Bei funktionalen Komponenten werden Hooks verwendet, um ähnliche Funktionalität zu erreichen.
Beispiel: In einer PublikationenListe-Komponente laden wir beim ersten Rendern Daten von einem Server:
import React, { useEffect, useState } from 'react';
function PublikationenListe() {
const [publikationen, setPublikationen] = useState([]);
useEffect(() => {
fetch('/api/publikationen')
.then(response => response.json())
.then(data => setPublikationen(data));
}, []); // Leeres Array bedeutet, dass es nur einmal ausgeführt wird
return (
<div>
{publikationen.map(publikation => (
<Publikation
key={publikation.id}
titel={publikation.titel}
abstract={publikation.abstract}
inhalt={publikation.inhalt}
/>
))}
</div>
);
}
Hier verwenden wir useEffect, um Daten beim ersten Rendern der Komponente abzurufen.
Virtual DOM
Der Virtual DOM ist eine in-memory-Repräsentation des echten DOMs. React verwendet den Virtual DOM, um Änderungen effizienter zu verarbeiten, indem es nur die Teile des echten DOMs aktualisiert, die tatsächlich verändert wurden. Diese Optimierung wird automatisch von React gehandhabt, daher müssen wir keinen speziellen Code dafür schreiben.
Event-Handling
React ermöglicht die Behandlung von Benutzerereignissen wie Klicks und Eingaben direkt innerhalb der JSX-Syntax.
Beispiel: In einer KommentarFormular-Komponente verarbeiten wir das Absenden des Formulars:
function KommentarFormular() {
const [kommentar, setKommentar] = useState();
const handleSubmit = (event) => {
event.preventDefault();
alert('Kommentar hinzugefügt: ' + kommentar);
setKommentar();
};
return (
<form onSubmit={handleSubmit}>
<textarea
value={kommentar}
onChange={(e) => setKommentar(e.target.value)}
placeholder="Fügen Sie einen Kommentar hinzu..."
/>
<button type="submit">Kommentar hinzufügen</button>
</form>
);
}
Hier wird der onSubmit-Event-Handler verwendet, um den Kommentar beim Absenden des Formulars zu verarbeiten.
Hooks
Hooks sind Funktionen, die es ermöglichen, in funktionalen Komponenten auf den State und andere React-Funktionen zuzugreifen.
Beispiel: Mit useState und useEffect können wir Zustand und Nebenwirkungen in funktionalen Komponenten verwalten:
import React, { useState, useEffect } from 'react';
function KommentarFormular() {
const [kommentar, setKommentar] = useState();
useEffect(() => {
console.log('KommentarFormular gerendert');
}, []);
return (
<form>
<textarea
value={kommentar}
onChange={(e) => setKommentar(e.target.value)}
placeholder="Fügen Sie einen Kommentar hinzu..."
/>
<button type="button" onClick={() => alert('Kommentar hinzugefügt: ' + kommentar)}>Kommentar hinzufügen</button>
</form>
);
}
Hier verwenden wir useState, um den Kommentar zu speichern, und useEffect, um einen Effekt nach dem ersten Rendern auszuführen.
Erste React Applikation in VSCode
Da wir nun die wichtigsten Konzepte, die React verwendet, kennengelernt haben, können wir nun unsere erste React App in VSCode ertellen.
Installiere Node.js und npm
Besuche die Node.js-Website und lade die neueste LTS-Version herunter. Dies installiert auch npm, das für das Verwalten von Paketen verwendet wird.
Installiere create-react-app
Öffne dein Terminal oder die Kommandozeile und installiere das create-react-app-Tool global:
npm install -g create-react-app
Erstelle ein neues React-Projekt
Gehen wir in das Verzeichnis, in dem das Projekt erstellt werden soll, und führen wir diesen Befehl aus:
npx create-react-app from-peer-review-to-crowd-review
Dieser Befehl erstellt ein neues Verzeichnis namens fromPeerReviewToCrowdReview mit einer grundlegenden React-Anwendung.
Öffne das Projekt in Visual Studio Code
Starte Visual Studio Code und öffne das Projektverzeichnis. Alternativ kannst man im Terminal folgenden Befehl verwenden:
code from-peer-review-to-crowd-review
Starte den Entwicklungsserver
Öffne das integrierte Terminal in VSCode (Terminal > Neues Terminal) und starte die Entwicklungsumgebung:
npm start
Dies startet den Entwicklungsserver und öffnet deine Anwendung in einem Webbrowser. Der Server überwacht Änderungen an deinem Code und aktualisiert die Anwendung automatisch.
Bearbeite die Anwendung
Gehe zur Datei src/App.js. Ändere den Code, um die Benutzeroberfläche für unsere Anwendung darzustellen:
import React from 'react';
import Publikation from './Publikation'; // Importiere die neue Komponente
function App() {
return (
<div className="App">
<header className="App-header">
<h1>Wissenschaftliche Publikationen</h1>
<Publikation
titel="Gibt es die Matrix wirklich?"
abstract="Eine Untersuchung der Realität und ihrer Möglichkeiten."
inhalt="Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt."
/>
</header>
</div>
);
}
export default App;
Füge eine neue Komponente hinzu
Erstelle eine neue Datei src/Publikation.js für die Publikation-Komponente:
import React from 'react';
function Publikation({ titel, abstract, inhalt }) {
return (
<div>
<h2>{titel}</h2>
<p>{abstract}</p>
<div>{inhalt}</div>
</div>
);
}
export default Publikation;
Füge weitere Komponenten hinzu
Wir können nun weitere Komponenten erstellen, die beispielsweise das Kommentarformular und andere Teile der Anwendung zu integrieren. Zum Beispiel, erstelle src/KommentarFormular.js:
import React, { useState } from 'react';
function KommentarFormular() {
const [kommentar, setKommentar] = useState();
const handleChange = (event) => {
setKommentar(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
alert('Kommentar hinzugefügt: ' + kommentar);
setKommentar();
};
return (
<form onSubmit={handleSubmit}>
<textarea
value={kommentar}
onChange={handleChange}
placeholder="Fügen Sie einen Kommentar hinzu..."
/>
<button type="submit">Kommentar hinzufügen</button>
</form>
);
}
export default KommentarFormular;
Importiere und verwende diese Komponente in App.js.
Angular
Angular ist ein weit verbreitetes Framework für die Entwicklung von Webanwendungen, das von Google entwickelt wird. Es basiert auf TypeScript und bietet eine strukturierte Architektur für den Aufbau von Single-Page-Anwendungen. Angular nutzt Komponenten als grundlegende Bausteine für die Benutzeroberfläche und bietet eine Vielzahl von Funktionen wie Datenbindung, Dependency Injection und Routing, um die Entwicklung und Wartung von komplexen Anwendungen zu erleichtern. Es enthält auch ein leistungsstarkes CLI (Command Line Interface) zum Generieren von Code und zur Verwaltung von Projekten. Angular ist bekannt für seine umfassenden Features und seine robuste Architektur, die es für große und skalierbare Projekte geeignet macht.
Komponenten
In Angular sind Komponenten die Hauptbausteine der Benutzeroberfläche. Jede Komponente besteht aus einer HTML-Vorlage, einer CSS-Datei für das Styling und einer TypeScript-Datei für die Logik.
Beispiel: Erstellen wir eine PublikationComponent, um eine Publikation anzuzeigen.
HTML-Datei (publikation.component.html):
<div>
<h2>Vorlage:Titel</h2>
<p>Vorlage:Abstract</p>
<div>Vorlage:Inhalt</div>
</div>
TypeScript-Datei (publikation.component.ts):
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-publikation',
templateUrl: './publikation.component.html',
styleUrls: ['./publikation.component.css']
})
export class PublikationComponent {
@Input() titel: string;
@Input() abstract: string;
@Input() inhalt: string;
}
Module
Angular-Anwendungen bestehen aus Modulen, die verschiedene Teile der Anwendung gruppieren. Ein Modul kann Komponenten, Dienste und andere Module enthalten.
Beispiel: Definieren wir ein Modul für die Publikationsfunktionalität.
TypeScript-Datei (app.module.ts):
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { PublikationComponent } from './publikation/publikation.component';
@NgModule({
declarations: [
AppComponent,
PublikationComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Services
Services sind wiederverwendbare Klassen, die Logik und Datenmanagement bereitstellen. Sie werden oft verwendet, um Daten zwischen Komponenten zu teilen.
Beispiel: Erstellen wir nun einen PublikationService, um Publikationen von einer API abzurufen.
TypeScript-Datei (publikation.service.ts):
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class PublikationService {
private apiUrl = 'https://api.example.com/publikationen';
constructor(private http: HttpClient) { }
getPublikationen(): Observable<any[]> {
return this.http.get<any[]>(this.apiUrl);
}
}
Routing
Angular-Routing ermöglicht das Navigieren zwischen verschiedenen Ansichten oder Komponenten innerhalb einer Anwendung.
Beispiel: Konfigurieren wir Routen für die Publikationsansicht und ein Kommentarformular.
TypeScript-Datei (app-routing.module.ts):
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PublikationComponent } from './publikation/publikation.component';
const routes: Routes = [
{ path: 'publikationen', component: PublikationComponent },
{ path: , redirectTo: '/publikationen', pathMatch: 'full' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Datenbindung
Angular bietet verschiedene Arten der Datenbindung, einschließlich Einweg- und Zweiweg-Datenbindung, um Daten zwischen der Logik der Komponente und der Ansicht zu synchronisieren.
Beispiel: Zeigen wir nun Daten aus dem PublikationService in der PublikationComponent an.
TypeScript-Datei (publikation.component.ts):
import { Component, OnInit } from '@angular/core';
import { PublikationService } from '../publikation.service';
@Component({
selector: 'app-publikation',
templateUrl: './publikation.component.html',
styleUrls: ['./publikation.component.css']
})
export class PublikationComponent implements OnInit {
publikationen: any[] = [];
constructor(private publikationService: PublikationService) { }
ngOnInit(): void {
this.publikationService.getPublikationen().subscribe(data => {
this.publikationen = data;
});
}
}
Forms
Angular bietet sowohl Template-driven Forms als auch Reactive Forms für die Verarbeitung von Benutzereingaben.
Beispiel: Erstellen wir ein Formular zum Hinzufügen von Kommentaren.
HTML-Datei (kommentar-formular.component.html):
<form (ngSubmit)="onSubmit()" #kommentarForm="ngForm">
<textarea
name="kommentar"
[(ngModel)]="kommentar"
placeholder="Fügen Sie einen Kommentar hinzu..."
required>
</textarea>
<button type="submit">Kommentar hinzufügen</button>
</form>
TypeScript-Datei (kommentar-formular.component.ts):
import { Component } from '@angular/core';
@Component({
selector: 'app-kommentar-formular',
templateUrl: './kommentar-formular.component.html',
styleUrls: ['./kommentar-formular.component.css']
})
export class KommentarFormularComponent {
kommentar: string = ;
onSubmit(): void {
alert('Kommentar hinzugefügt: ' + this.kommentar);
this.kommentar = ;
}
}
Dependency Injection
Angular verwendet Dependency Injection (DI), um Abhängigkeiten wie Services in Komponenten und andere Services einzufügen.
Beispiel: Der PublikationService wird in PublikationComponent durch DI eingefügt.
TypeScript-Datei (publikation.component.ts):
import { Component, OnInit } from '@angular/core';
import { PublikationService } from '../publikation.service';
@Component({
selector: 'app-publikation',
templateUrl: './publikation.component.html',
styleUrls: ['./publikation.component.css']
})
export class PublikationComponent implements OnInit {
publikationen: any[] = [];
constructor(private publikationService: PublikationService) { }
ngOnInit(): void {
this.publikationService.getPublikationen().subscribe(data => {
this.publikationen = data;
});
}
}
Mein erstes Angular Projekt in VSCode
Stellen wir zuerst sicher, dass Node.js auf deinem System installiert ist. Node.js kann von der Node.js-Website heruntergeladen und installieren werden.
Installiere Angular CLI global, um ein neues Angular-Projekt zu erstellen:
npm install -g @angular/cli
Erstelle ein neues Angular-Projekt
Öffne das Terminal oder die Kommandozeile und navigiere zu dem Verzeichnis, in dem das Projekt erstellt werden soll.
Führe den folgenden Befehl aus, um ein neues Angular-Projekt zu erstellen:
ng new from-peer-review-to-crowd-review
Wähle "Ja" um Angular Routing zu verwenden und verwende das Standard-Stilformat (z. B. CSS).
Öffne das Projekt in Visual Studio Code
Starte Visual Studio Code und öffne das Projektverzeichnis:
code from-peer-review-to-crowd-review
Erstelle eine Komponente für die Publikation
Erstelle eine neue Komponente für die Publikationen:
ng generate component publication
HTML-Datei (src/app/publikation/publikation.component.html):
<div>
<h2>Vorlage:Titel</h2>
<p>Vorlage:Abstract</p>
<div>Vorlage:Inhalt</div>
</div>
TypeScript-Datei (src/app/publikation/publikation.component.ts):
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-publikation',
templateUrl: './publikation.component.html',
styleUrls: ['./publikation.component.css']
})
export class PublikationComponent {
@Input() titel: string;
@Input() abstract: string;
@Input() inhalt: string;
}
Erstelle eine Komponente für das Kommentarformular
Erstelle eine neue Komponente für das Kommentarformular:
ng generate component kommentar-formular
HTML-Datei (src/app/kommentar-formular/kommentar-formular.component.html):
<form (ngSubmit)="onSubmit()" #kommentarForm="ngForm">
<textarea
name="kommentar"
[(ngModel)]="kommentar"
placeholder="Fügen Sie einen Kommentar hinzu..."
required>
</textarea>
<button type="submit">Kommentar hinzufügen</button>
</form>
TypeScript-Datei (src/app/kommentar-formular/kommentar-formular.component.ts):
import { Component } from '@angular/core';
@Component({
selector: 'app-kommentar-formular',
templateUrl: './kommentar-formular.component.html',
styleUrls: ['./kommentar-formular.component.css']
})
export class KommentarFormularComponent {
kommentar: string = ;
onSubmit(): void {
alert('Kommentar hinzugefügt: ' + this.kommentar);
this.kommentar = ;
}
}
Füge Routing hinzu
TypeScript-Datei (src/app/app-routing.module.ts):
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { PublikationComponent } from './publikation/publikation.component';
import { KommentarFormularComponent } from './kommentar-formular/kommentar-formular.component';
const routes: Routes = [
{ path: 'publikationen', component: PublikationComponent },
{ path: , redirectTo: '/publikationen', pathMatch: 'full' }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
TypeScript-Datei (src/app/app.module.ts): Füge die neuen Komponenten und das FormsModule hinzu:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // Importiere FormsModule
import { AppComponent } from './app.component';
import { PublikationComponent } from './publikation/publikation.component';
import { KommentarFormularComponent } from './kommentar-formular/kommentar-formular.component';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
declarations: [
AppComponent,
PublikationComponent,
KommentarFormularComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule // Füge FormsModule hinzu
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Starte die Anwendung
Starte den Angular-Entwicklungsserver, um deine Anwendung auszuführen:
ng serve
Öffne einen Webbrowser und gehe zu http://localhost:4200, um die Anwendung zu sehen.
Verändere die app.component.html
HTML-Datei (src/app/app.component.html): Ersetze den Standardinhalt, um die PublikationComponent und KommentarFormularComponent einzuschließen:
<div class="app">
<h1>Wissenschaftliche Publikationen</h1>
<app-publikation
titel="Gibt es die Matrix wirklich?"
abstract="Eine Untersuchung der Realität und ihrer Möglichkeiten."
inhalt="Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt.">
</app-publikation>
<app-kommentar-formular></app-kommentar-formular>
</div>
Nun haben wir eine grundlegende Angular-Anwendung erstellt, die eine Publikation anzeigt und ein Kommentarformular enthält. Diese Anwendung verwendet grundlegende Angular-Konzepte wie Komponenten, Module, Routing und Formulare.
Vue.js
Vue.js ist besonders für seine Einfachheit und Flexibilität bekannt. Vue.js verwendet eine deklarative Syntax, bei der die Benutzeroberfläche mit einem reaktiven Datenmodell verknüpft ist, was bedeutet, dass sich die UI automatisch aktualisiert, wenn sich die zugrunde liegenden Daten ändern. Es basiert auf Komponenten, die HTML, CSS und JavaScript in einer einzigen Datei kombinieren, was die Entwicklung und Wartung von Anwendungen erleichtert. Vue.js ist leichtgewichtig, leicht erlernbar und lässt sich gut in bestehende Projekte integrieren oder für die Entwicklung von neuen, komplexeren Anwendungen nutzen.
Komponenten
In Vue.js sind Komponenten wiederverwendbare und isolierte Einheiten, die HTML, CSS und JavaScript zusammenfassen.
Beispiel: Erstellen wir eine Publikation-Komponente, um eine Publikation darzustellen.
Datei Publikation.vue:
<template>
<div>
<h2>Vorlage:Titel</h2>
<p>Vorlage:Abstract</p>
<div>Vorlage:Inhalt</div>
</div>
</template>
<script>
export default {
props: {
titel: String,
abstract: String,
inhalt: String
}
}
</script>
<style scoped>
/* Styles für die Publikation */
</style>
Reaktive Datenbindung
Vue.js verwendet reaktive Datenbindung, um sicherzustellen, dass Änderungen an Daten automatisch in der Benutzeroberfläche angezeigt werden.
Beispiel: Verwenden wir eine data-Eigenschaft in einer App-Komponente, um eine Liste von Publikationen zu verwalten.
Datei App.vue:
<template>
<div id="app">
<h1>Wissenschaftliche Publikationen</h1>
<Publikation
v-for="(publikation, index) in publikationen"
- key="index"
- titel="publikation.titel"
- abstract="publikation.abstract"
- inhalt="publikation.inhalt"
/>
<KommentarFormular />
</div>
</template>
<script>
import Publikation from './components/Publikation.vue';
import KommentarFormular from './components/KommentarFormular.vue';
export default {
components: {
Publikation,
KommentarFormular
},
data() {
return {
publikationen: [
{
titel: 'Gibt es die Matrix wirklich?',
abstract: 'Eine Untersuchung der Realität und ihrer Möglichkeiten.',
inhalt: 'Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt.'
}
]
}
}
}
</script>
<style>
/* Styles für die App */
</style>
Props
Props sind Eigenschaften, die von einer übergeordneten Komponente an eine untergeordnete Komponente übergeben werden, um Daten zu übermitteln.
Beispiel: Die Publikation-Komponente erhält titel, abstract und inhalt als Props.
In Publikation.vue:
<template>
<div>
<h2>Vorlage:Titel</h2>
<p>Vorlage:Abstract</p>
<div>Vorlage:Inhalt</div>
</div>
</template>
<script>
export default {
props: {
titel: String,
abstract: String,
inhalt: String
}
}
</script>
Event Handling
Vue.js ermöglicht es, Benutzeraktionen wie Klicks und Eingaben zu erfassen und darauf zu reagieren.
Beispiel: Erstellen wir nun ein Kommentarformular, das einen Kommentar hinzufügt und anzeigt.
Datei KommentarFormular.vue:
<template>
<form @submit.prevent="onSubmit">
<textarea v-model="kommentar" placeholder="Fügen Sie einen Kommentar hinzu..." required></textarea>
<button type="submit">Kommentar hinzufügen</button>
</form>
</template>
<script>
export default {
data() {
return {
kommentar:
}
},
methods: {
onSubmit() {
alert('Kommentar hinzugefügt: ' + this.kommentar);
this.kommentar = ;
}
}
}
</script>
<style scoped>
/* Styles für das Kommentarformular */
</style>
Vue Router
Vue Router ist eine offizielle Router-Bibliothek für Vue.js, die das Routing innerhalb der Anwendung ermöglicht.
Beispiel: Konfigurieren wir nun Routen, um zwischen verschiedenen Komponenten zu navigieren.
Datei router/index.js:
import Vue from 'vue';
import Router from 'vue-router';
import Publikation from '../components/Publikation.vue';
import KommentarFormular from '../components/KommentarFormular.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/publikationen',
name: 'Publikation',
component: Publikation
},
{
path: '/',
name: 'KommentarFormular',
component: KommentarFormular
}
]
});
In der Hauptdatei main.js:
import Vue from 'vue';
import App from './App.vue';
import router from './router';
Vue.config.productionTip = false;
new Vue({
router,
render: h => h(App)
}).$mount('#app');
Vuex
Vuex ist eine State-Management-Bibliothek für Vue.js-Anwendungen, die ein zentrales Repository für alle Komponenten bereitstellt.
Beispiel: Verwende Vuex für die Verwaltung der Publikationen.
Datei store/index.js:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
publikationen: [
{
titel: 'Gibt es die Matrix wirklich?',
abstract: 'Eine Untersuchung der Realität und ihrer Möglichkeiten.',
inhalt: 'Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt.'
}
]
},
mutations: {
addPublikation(state, publikationen) {
state.publikationen.push(publikationen);
}
},
actions: {
addPublikation({ commit }, publikationen) {
commit('addPublikation', publikationen);
}
}
});
In App.vue:
<template>
<div id="app">
<h1>Wissenschaftliche Publikationen</h1>
<Publikation
v-for="(publikation, index) in $store.state.publikationen"
- key="index"
- titel="publikation.titel"
- abstract="publikation.abstract"
- inhalt="publikation.inhalt"
/>
<KommentarFormular />
</div>
</template>
Mit diesen Konzepten kann man strukturierte Vue.js-Anwendung erstellen, die eine Publikation anzeigt und ein Kommentarformular enthält.
Mein erstes Vue.js Projekt in VSCode
Es beginnt wieder damit sicherzustellen, dass Node.js auf deinem System installiert ist. Falls nicht, lade es von der Node.js-Website herunter und installiere es.
Installiere Vue CLI global, um ein neues Vue-Projekt zu erstellen:
npm install -g @vue/cli
Erstelle ein neues Vue-Projekt
Öffne das Terminal oder die Kommandozeile und navigiere zu dem Verzeichnis, in dem das Projekt erstellt werden soll. Führe den folgenden Befehl aus:
vue create from-peer-review-to-crowd-review
Wähle die Standardkonfiguration oder passe sie nach Bedarf an.
Öffne das Projekt in Visual Studio Code
Starte Visual Studio Code und öffne das neu erstellte Projektverzeichnis:
code from-peer-review-to-crowd-review
4. Erstelle Komponenten
Erstelle eine neue Datei für die Publikation-Komponente:
- Erstelle einen neuen Ordner components im src-Verzeichnis
- Füge eine Datei Publikation.vue im src/components-Ordner hinzu
Datei src/components/Publikation.vue:
<template>
<div>
<h2>Vorlage:Titel</h2>
<p>Vorlage:Abstract</p>
<div>Vorlage:Inhalt</div>
</div>
</template>
<script>
export default {
props: {
titel: String,
abstract: String,
inhalt: String
}
}
</script>
<style scoped>
/* Styles für die Publikation */
</style>
Füge eine Datei KommentarFormular.vue im src/components-Ordner hinzu.
Datei src/components/KommentarFormular.vue:
<template>
<form @submit.prevent="onSubmit">
<textarea v-model="kommentar" placeholder="Fügen Sie einen Kommentar hinzu..." required></textarea>
<button type="submit">Kommentar hinzufügen</button>
</form>
</template>
<script>
export default {
data() {
return {
kommentar:
}
},
methods: {
onSubmit() {
alert('Kommentar hinzugefügt: ' + this.kommentar);
this.kommentar = ;
}
}
}
</script>
<style scoped>
/* Styles für das Kommentarformular */
</style>
Konfiguriere Routing
Falls das Projekt noch keinen Router enthält, installiere Vue Router:
npm install vue-router
Erstelle eine Datei router/index.js im src-Verzeichnis:
Datei src/router/index.js:
import Vue from 'vue';
import Router from 'vue-router';
import Publikation from '../components/Publikation.vue';
import KommentarFormular from '../components/KommentarFormular.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/publikationen',
name: 'Publikation',
component: Publikation
},
{
path: '/',
name: 'KommentarFormular',
component: KommentarFormular
}
]
});
Verwende die Komponenten in App.vue
Ersetze den Inhalt der App.vue, um die Publikation- und KommentarFormular-Komponenten einzuschließen:
Datei src/App.vue:
<template>
<div id="app">
<h1>Wissenschaftliche Publikationen</h1>
<Publikation
v-for="(publikation, index) in publikationen"
- key="index"
- titel="publikation.titel"
- abstract="publikation.abstract"
- inhalt="publikation.inhalt"
/>
<KommentarFormular />
</div>
</template>
<script>
import Publikation from './components/Publikation.vue';
import KommentarFormular from './components/KommentarFormular.vue';
export default {
components: {
Publikation,
KommentarFormular
},
data() {
return {
publikationen: [
{
titel: 'Gibt es die Matrix wirklich?',
abstract: 'Eine Untersuchung der Realität und ihrer Möglichkeiten.',
inhalt: 'Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt.'
}
]
}
}
}
</script>
<style>
/* Styles für die App */
</style>
Starte die Anwendung
Starte den Vue-Entwicklungsserver, um die Anwendung auszuführen:
npm run serve
Öffne einen Webbrowser und gehe zu http://localhost:8080, um die Anwendung zu sehen.
Jetzt haben wir ein funktionierendes Vue.js-Projekt erstellt, welches eine Publikation anzeigt und ein Kommentarformular enthält.
Asynchrone Programmierung und Datenübertragung
Frontend-Entwicklung konzentriert sich auf die Gestaltung der Benutzeroberfläche und Interaktivität einer Webanwendung unter Verwendung moderner Technologien wie HTML5, CSS3 und JavaScript-Frameworks wie React, Angular oder Vue.js. Im Full-Stack-Kontext arbeitet das Frontend mit dem Backend zusammen, das durch Technologien wie Node.js, Express und Datenbanken wie MongoDB oder PostgreSQL unterstützt wird. Die Kommunikation zwischen Frontend und Backend erfolgt typischerweise durch RESTful APIs oder GraphQL, wobei JSON oder XML als Formate für den Datenaustausch verwendet werden. Promises und async/await sind Methoden zur Handhabung von asynchronem Code in JavaScript. Sie helfen dabei, Code lesbarer und wartbarer zu machen, insbesondere wenn man mit asynchronen Operationen wie API-Anfragen oder Datenverarbeitung arbeitet.
Sehen wir uns nun an, wie man Promises und async/await in unserem Beispiel anwenden kann. Promises sind Objekte, die einen zukünftigen Wert repräsentieren. Sie bieten eine Möglichkeit, asynchrone Operationen zu verwalten, indem sie auf den Abschluss dieser Operation warten.
Angenommen, wir möchten die Publikationen von einem Server abrufen. Wir verwenden eine Funktion, die ein Promise zurückgibt:
JavaScript Code:
// Funktion zum Abrufen von Publikationen (simuliert mit setTimeout)
function fetchPublikationen() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const publikationen = [
{
titel: 'Gibt es die Matrix wirklich?',
abstract: 'Eine Untersuchung der Realität und ihrer Möglichkeiten.',
inhalt: 'Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt.'
}
];
resolve(publikationen);
}, 1000);
});
}
// Nutzung des Promises
fetchPublikationen().then(publikationen => {
console.log('Publikationen erhalten:', publikationen);
}).catch(error => {
console.error('Fehler beim Abrufen der Publikationen:', error);
});
In diesem Beispiel simulieren wir die asynchrone Abrufoperation mit setTimeout. Die Funktion fetchPublikationen gibt ein Promise zurück, das nach einer Verzögerung von 1 Sekunde die Publikationen auflöst (resolve). Wenn ein Fehler auftritt, wird die Funktion reject aufgerufen.
async/await
async/await ist eine syntaktische Vereinfachung für die Arbeit mit Promises, die es ermöglicht, asynchrone Operationen wie synchronen Code zu schreiben.
Wir können das gleiche Beispiel mit async/await umsetzen:
JavaScript Code:
// Funktion zum Abrufen von Publikationen (simuliert mit setTimeout)
function fetchPublikationen() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const publikationen = [
{
titel: 'Gibt es die Matrix wirklich?',
abstract: 'Eine Untersuchung der Realität und ihrer Möglichkeiten.',
inhalt: 'Hier wird die Forschung zu den Fragen der Matrix-Theorie vorgestellt.'
}
];
resolve(publikationen);
}, 1000);
});
}
// Async-Funktion zum Abrufen und Anzeigen von Publikationen
async function showPublikationen() {
try {
const publikationen = await fetchPublikationen();
console.log('Publikationen erhalten:', publikationen);
} catch (error) {
console.error('Fehler beim Abrufen der Publikationen:', error);
}
}
// Aufruf der async-Funktion
showPublikationen();
Dieses Beispiel erläutert:
- fetchPublikationen bleibt unverändert und gibt ein Promise zurück
- showPublikationen ist eine async Funktion. Innerhalb dieser Funktion verwenden wir await, um auf das Ergebnis von fetchPublikationen zu warten. Await pausiert die Ausführung der Funktion, bis das Promise aufgelöst wird.
- Fehler werden mit try/catch behandelt, was den Code sauber und verständlich macht
Daten zwischen dem Backend und dem Frontend können in mehreren Formaten gesendet werden, meistens wird entweder XML oder JSON verwendet. XML (eXtensible Markup Language) ist ein markiertes Datenformat, das Daten in einer hierarchischen Struktur mit benutzerdefinierten Tags darstellt. Es ist sehr flexibel und kann komplexe Datenstrukturen repräsentieren, wird jedoch als schwerfälliger und aufwändiger in der Verarbeitung angesehen. JSON (JavaScript Object Notation) ist ein leichteres Format, das Daten in einer einfacheren Schlüssel-Wert-Paar-Struktur organisiert. JSON ist leichter lesbar und einfacher zu verarbeiten, insbesondere in JavaScript-Umgebungen. In der Praxis wird JSON häufiger verwendet als XML, da es einfacher zu integrieren und effizienter in modernen Webanwendungen ist. JSON lässt sich nahtlos mit JavaScript kombinieren und ermöglicht eine schnellere und unkompliziertere Datenverarbeitung.
AJAX (Asynchronous JavaScript and XML) ermöglicht die asynchrone Kommunikation zwischen dem Browser und dem Server, wodurch Inhalte dynamisch aktualisiert werden können, ohne die ganze Seite neu zu laden. In unserem Beispiel für eine Plattform zur Veröffentlichung wissenschaftlicher Publikationen können wir AJAX verwenden, um Publikationen vom Server abzurufen und auf der Webseite anzuzeigen. Obwohl der Name "AJAX" XML impliziert, wird in der Praxis oft JSON verwendet.
Beispiel einer XML-Datei:
<publikation>
<titel> Die Matrix: Leben wir in einer Simulation?</titel>
<autor>Alice</autor>
<jahr>2024</jahr>
</publikation>
Und hier dieselbe Information als JSON-Datei:
{
"titel":"Die Matrix: Leben wir in einer Simulation?",
"autor": "Alice",
"jahr": 2024
}
Senden wir nun eine Anfrage mit der fetch-API. Der Server liefert die Publikationen im JSON-Format zurück. Diese Daten werden dann verarbeitet und in der Benutzeroberfläche angezeigt, ohne dass die Seite neu geladen wird.
async function fetchPublikationen() {
try {
const response = await fetch('https://api.example.com/publikationen');
if (!response.ok) {
throw new Error('Netzwerkantwort war nicht okay.');
}
const data = await response.json();
console.log('Publikationen erhalten:', data);
displayPublikationen(data);
} catch (error) {
console.error('Fehler beim Abrufen der Publikationen:', error);
}
}
function displayPublikationen(publikationen) {
const container = document.getElementById('publikationen-container');
container.innerHTML = publikationen.map(p => `
<div>
<h2>${p.titel}</h2>
<p>${p.autor}</p>
<div>${p.jahr}</div>
</div>
`).join();
}
fetchPublikationen();
In diesem Code wird eine Anfrage an die API gesendet, um Publikationen zu erhalten. Die JSON-Daten werden dann verarbeitet und die Inhalte auf der Webseite angezeigt, was eine dynamische und reaktive Benutzererfahrung ermöglicht. Es ist üblich Beispiel-Serverantworten und -anfragen lokal zu speichern und diese Daten (üblicherweise in der Praxis oft JSON-Dateien) im Frontend zu verwenden, also die Daten anhand von diesen JSON Dateien anzuzeigen.
API Definitionen
API-Definitionen sind von zentraler Bedeutung für die Erstellung klarer und konsistenter Schnittstellen, die den Datenaustausch zwischen verschiedenen Systemen regeln. Sie bieten eine strukturierte Übersicht über verfügbare Endpunkte, erforderliche Parameter und die Formate der zurückgegebenen Daten, was die Integration von Frontend und Backend vereinfacht. OpenAPI (The Linux Foundation, 2024), ehemals bekannt als Swagger, ist ein weit verbreitetes Tool zur Definition und Dokumentation von APIs. Mit OpenAPI können Entwickler präzise API-Spezifikationen in einem maschinenlesbaren Format erstellen, das auch interaktive Dokumentation umfasst. Diese Dokumentation erleichtert es Entwicklern, die API zu verstehen und zu testen, ohne direkt mit dem Backend-Code interagieren zu müssen. OpenAPI unterstützt die klare Kommunikation der API-Funktionalitäten und trägt zur Konsistenz und Interoperabilität bei der Systemintegration bei.
Um die OpenAPI-Spezifikation für unsere Plattform zur Veröffentlichung wissenschaftlicher Publikationen visuell anzusehen und zu testen, können wir die Swagger UI verwenden. Hier ist eine Schritt-für-Schritt-Anleitung, wie dies aussehen kann:
Swagger UI verwenden
Swagger UI lokal einrichten:
- Lade die Swagger UI herunter oder klone das Repository
- Öffne das Verzeichnis dist und kopiere die Dateien swagger-ui-bundle.js, swagger-ui-standalone-preset.js und swagger-ui.css in ein Verzeichnis, das von deinem Webserver bereitgestellt wird
OpenAPI-Spezifikation einbinden:
Erstelle eine HTML-Datei, zum Beispiel index.html, im selben Verzeichnis wie die Swagger UI Dateien und binde die OpenAPI-Spezifikation ein. Die index.html könnte folgendermaßen aussehen:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="swagger-ui.css" >
<script src="swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: "path/to/your/openapi.yaml", // Pfad zu deiner OpenAPI-Spezifikation
dom_id: '#swagger-ui',
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
layout: "StandaloneLayout"
});
window.ui = ui;
}
</script>
</head>
<body>
<div id="swagger-ui"></div>
</body>
</html>
Ersetze path/to/your/openapi.yaml durch den Pfad zu deiner OpenAPI-Spezifikation.
Swagger UI lokal öffnen:
Starte einen lokalen Webserver, um die index.html Datei anzuzeigen. Zum Beispiel kannst man dies mit Python tun: python -m http.server im Verzeichnis mit der index.html Datei.
Öffne deinen Browser und navigiere zu der URL, die deinem lokalen Webserver zugewiesen ist, wie http://localhost:8000, um die interaktive API-Dokumentation deiner Publikationen-Plattform zu sehen.
API Definition für unser Fallbeispiel
In unserem Beispiel könnte man sich folgende vereinfachte API Definitionen vorstellen:
POST /register
POST /login
POST /publications
GET /publications/{id}
POST /reviews
GET /comments?publicationId={id}
POST erstellt neue Daten auf dem Server. PUT aktualisiert bestehende Daten. GET ruft Daten vom Server ab, ohne sie zu ändern. Im Frontend Development ist sollte man immer die gesamte Applikation verstehen und wie die Daten am effizientesten zwischen dem Server und dem Frontend ausgetauscht werden können. Deshalb ist es wichtig sich die API-Definition, sowie das UI-Design, am Anfang eines neuen Frontendprojekts gut zu überlegen. Die API-Definition ist der Vertrag zwischen der UI und dem Server. Sehen wir uns nun die Datenübertragung für ein paar Endpunkte im Detail an.
- POST /register
Beschreibung: Registriert einen neuen Benutzer im System.
Anfrage:
{
"username": "alice",
"email": "alice@example.com",
"password": "securepassword",
"role": "Author"
}
Antwort:
{
"id": 1,
"username": "alice",
"email": "alice@example.com",
"role": "Author"
}
POST /login
Beschreibung: Authentifiziert einen Benutzer und erstellt eine Sitzung.
Anfrage:
{
"email": "alice@example.com",
"password": "securepassword"
}
Antwort:
{
"token": "jwt-token-string"
}
POST /publications
Beschreibung:Erstellt eine neue wissenschaftliche Publikation.
Anfrage:
{
"title": "Einfluss von KI auf Peer-Review-Prozesse",
"abstract": "Diese Arbeit untersucht...",
"content": "Der komplette Inhalt...",
"authorId": 1
}
Antwort:
{
"id": 101,
"title": "Einfluss von KI auf Peer-Review-Prozesse",
"status": "Eingereicht"
}
GET /publications/{id}
Beschreibung: Gibt Details zu einer spezifischen Publikation zurück.
Parameter:
- id (Pfadparameter): Die ID der Publikation.
Antwort:
{
"id": 101,
"title": "Einfluss von KI auf Peer-Review-Prozesse",
"abstract": "Diese Arbeit untersucht...",
"content": "Der komplette Inhalt...",
"status": "Eingereicht",
"authorId": 1
}
POST /reviews
Beschreibung: Ein Gutachter erstellt ein Gutachten für eine Publikation.
Anfrage:
{
"publicationId": 101,
"reviewerId": 2,
"comments": "Die Arbeit ist gut, aber...",
"recommendation": "Kleine Überarbeitung"
}
Antwort:
{
"id": 201,
"publicationId": 101,
"reviewerId": 2,
"status": "Gutachten erstellt"
}
GET /comments?publicationId={id}
Beschreibung: Listet alle Kommentare zu einer Publikation auf.
Parameter:
- publicationId (Query-Parameter): Die ID der Publikation.
Antwort:
[
{
"id": 301,
"publicationId": 101,
"userId": 3,
"content": "Sehr interessante Ergebnisse!"
},
{
"id": 302,
"publicationId": 101,
"userId": 4,
"content": "Ich stimme dem Gutachter zu, aber..."
}
]
Alternative Tools
Es gibt auch online Tools zur API-Dokumentation. Beispielsweise:
- Swagger Editor (SmartBear, 2024): Besuche Swagger Editor, lade eine OpenAPI-Spezifikation hoch oder füge den Inhalt direkt ein, um die API-Dokumentation zu erstellen und zu testen.
- Postman (Postman, Inc., 2024): Lade eine OpenAPI-Spezifikation in Postman, um die API-Dokumentation anzuzeigen und API-Anfragen zu testen.
Diese Tools helfen, die API-Dokumentation für die Plattform zu visualisieren und zu überprüfen, wie die API funktioniert.
Responsive Webdesign
Responsive Webdesign sorgt dafür, dass Websites auf allen Geräten gut aussehen, indem sie sich automatisch an verschiedene Bildschirmgrößen anpassen. Zu den Prinzipien gehören flexible Layouts, die sich an unterschiedliche Bildschirmgrößen anpassen, skalierbare Bilder und Schriften sowie die Verwendung von Media Queries in CSS, um spezifische Stile für verschiedene Geräte zu definieren. Ziel ist es, eine konsistente und nutzerfreundliche Erfahrung auf Smartphones, Tablets und Desktops zu bieten.
Gestaltung von Benutzeroberflächen, die auf verschiedenen Geräten und Bildschirmgrößen gut funktionieren
Sehen wir uns ein paar HTML und CSS-Konzepte an, die es ermöglichen Elemente unterschiedlich auf unterschiedlichen Geräten darzustellen. Die besprochenen JavaScript Frameworks helfen auch dabei Websites zu designen die sowohl auf großen Bildschirmen als auch auf Smartphones gut bedienbar sind.
Responsive Layout
Verwende Flexbox für ein flexibles Layout, das sich an verschiedene Bildschirmgrößen anpasst.
<!-- HTML-Struktur -->
<div class="publikationen-container">
<div class="publikation">
<h2>Publikation 1</h2>
<p>Abstract...</p>
</div>
<div class="publikation">
<h2>Publikation 2</h2>
<p>Abstract...</p>
</div>
<!-- Weitere Publikationen -->
</div>
/* CSS für responsives Layout */
.publikationen-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.publikation {
flex: 1 1 calc(33.333% - 32px); /* Drei Spalten Layout mit Abstand */
box-sizing: border-box;
}
@media (max-width: 768px) {
.publikation {
flex: 1 1 calc(50% - 32px); /* Zwei Spalten Layout auf Tablets */
}
}
@media (max-width: 480px) {
.publikation {
flex: 1 1 100%; /* Einspaltiges Layout auf Mobilgeräten */
}
}
Media Queries
Passe Stile für unterschiedliche Bildschirmgrößen an, um das Layout und die Schriftgröße zu optimieren.
/* Media Queries für unterschiedliche Bildschirmgrößen */
@media (max-width: 1200px) {
.header {
font-size: 1.5em;
}
}
@media (max-width: 768px) {
.header {
font-size: 1.2em;
}
.navigation {
display: none; /* Navigation auf kleineren Bildschirmen ausblenden */
}
}
Flexible Bilder
Stelle sicher, dass Bilder sich proportional zur Bildschirmgröße skalieren.
/* Flexibles Bild */
img {
max-width: 100%;
height: auto;
}
Touchfreundliche Elemente
Gestalte Schaltflächen und Links groß genug für eine einfache Bedienung auf Touchscreens.
/* Touchfreundliche Schaltflächen */
button {
padding: 12px 20px;
font-size: 16px;
}
Testen
Nutze Entwicklertools in Browsern oder echte Geräte, um das Layout und die Funktionalität auf verschiedenen Bildschirmgrößen zu überprüfen. Mit diesen Techniken und Beispielen kannst man sicherstellen, dass unsere Plattform für wissenschaftliche Publikationen auf allen Geräten gut aussieht und benutzerfreundlich ist.
Medienabfragen und die Verwendung von CSS-Frameworks zur Unterstützung des responsiven Designs
Medienabfragen
Medienabfragen ermöglichen es, CSS-Stile basierend auf den Eigenschaften des Geräts wie Bildschirmgröße und -auflösung anzupassen. Sie sind besonders nützlich, um sicherzustellen, dass deine Plattform auf verschiedenen Bildschirmgrößen gut aussieht.
Beispiel: Wir möchten das Layout der Publikationen auf unterschiedlichen Geräten anpassen.
/* Standardlayout für große Bildschirme */
.publikationen-container {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.publikation {
flex: 1 1 calc(33.333% - 32px); /* Drei Spalten Layout für große Bildschirme */
box-sizing: border-box;
}
/* Layout für Tablets */
@media (max-width: 768px) {
.publikation {
flex: 1 1 calc(50% - 32px); /* Zwei Spalten Layout für Tablets */
}
}
/* Layout für Mobilgeräte */
@media (max-width: 480px) {
.publikation {
flex: 1 1 100%; /* Einspaltiges Layout für Mobilgeräte */
}
}
Verwendung von CSS-Frameworks
CSS-Frameworks bieten vorgefertigte Klassen und Komponenten, die helfen, responsives Design schnell und einfach zu implementieren. Beliebte Frameworks sind Bootstrap, Foundation und Tailwind CSS.
Bootstrap ist ein weit verbreitetes CSS-Framework, das eine Reihe von nützlichen Klassen für responsives Design bereitstellt. Füge die Bootstrap CSS-Datei in deinem HTML-Dokument ein.
<!-- Bootstrap CSS einbinden -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css%22>
Verwende Bootstrap-Klassen, um ein responsives Layout für deine Publikationen zu erstellen.
<!-- HTML-Struktur mit Bootstrap-Klassen -->
<div class="container">
<div class="row">
<div class="col-md-4 mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Publikation 1</h5>
<p class="card-text">Abstract...</p>
</div>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">Publikation 2</h5>
<p class="card-text">Abstract...</p>
</div>
</div>
</div>
<!-- Weitere Publikationen -->
</div>
</div>
In diesem Beispiel verwendet die Plattform Bootstrap-Klassen wie container, row und col-md-4, um ein responsives Raster zu erstellen, das sich je nach Bildschirmgröße anpasst. Bootstrap sorgt dafür, dass das Layout auf großen Bildschirmen in drei Spalten und auf kleineren Bildschirmen in einer oder zwei Spalten angezeigt wird. Durch die Kombination von Medienabfragen und CSS-Frameworks kann man sicherstellen, dass deine Plattform zur Veröffentlichung wissenschaftlicher Publikationen auf verschiedenen Geräten gut aussieht und benutzerfreundlich ist.
Leistungsoptimierung
Niemand wartet gerne mehrere Sekunden, bis eine Website vollständig geladen ist. Jede Website, die wir entwickeln sollte, immer so optimiert wie möglich sein. Performance-Benchmarks messen, wie schnell und gut eine Website läuft. Sie helfen dabei, die Benutzererfahrung zu verbessern. Es ist ratsam die Performance einer Website immer wieder zu messen, um sicherzugehen dass man Ladezeiten mit neuen Grafiken oder anderen Elementen unnötig verlängert hat.
Optimierung von Ladezeiten
Szenario: Die Seite lädt eine Liste von Publikationen, einschließlich Titel, Abstract und Inhaltszusammenfassung.
Wir haben folgende Optimierungsmöglichkeiten:
Lazy Loading: Lade Inhalte nur dann, wenn sie tatsächlich benötigt werden. Anstatt alle Publikationen auf einmal zu laden, zeige zunächst nur eine Übersicht an und lade detaillierte Informationen erst, wenn der Benutzer mehr darüber erfahren möchte. Dies reduziert die anfängliche Ladezeit erheblich.
Caching: Verwende Browser-Caching oder serverseitiges Caching, um häufig abgerufene Daten zwischenzuspeichern. Wenn eine Publikation einmal abgerufen wurde, speichere diese Daten lokal oder auf dem Server, um sie bei zukünftigen Anfragen schneller bereitstellen zu können. Dies vermindert die Notwendigkeit, dieselben Daten wiederholt vom Server abzurufen.
Minimierung von HTTP-Anfragen: Reduziere die Anzahl der HTTP-Anfragen durch das Zusammenfassen von CSS- und JavaScript-Dateien. Anstatt mehrere Dateien zu laden, kombiniere sie in einer einzigen Datei, um die Anzahl der Anfragen zu minimieren und die Ladezeit zu verkürzen.
Komprimierung: Komprimiere die Daten, die zwischen Server und Client ausgetauscht werden. Verwende Gzip oder Brotli-Komprimierung, um die Größe der übertragenen Daten zu reduzieren. Dies verringert die Menge an Daten, die heruntergeladen werden müssen, und beschleunigt die Ladezeiten.
Optimierung von Bildern: Stelle sicher, dass alle Bilder auf der Website komprimiert und in einem Web-freundlichen Format vorliegen. Verwende Formate wie WebP oder JPEG 2000, die eine bessere Komprimierung bieten, um die Größe der Bilddateien zu reduzieren und die Ladezeiten zu verbessern.
Content Delivery Network (CDN): Nutze ein CDN, um statische Dateien wie Bilder, CSS und JavaScript von Servern in der Nähe des Benutzers zu liefern. Ein CDN kann die Ladezeiten durch geografische Verteilung und schnelle Bereitstellung von Inhalten verbessern.
Lazy Loading
Lade Publikationen nur bei Bedarf, nicht alle auf einmal. Hier wird zunächst nur eine Übersicht oder ein Teaser angezeigt, und detaillierte Informationen werden erst geladen, wenn der Benutzer auf „Mehr lesen“ klickt oder scrollt.
// Funktion zum Laden der Details einer Publikation auf Knopfdruck
async function loadPublikationDetails(publikationId) {
try {
const response = await fetch(`https://api.example.com/publikationen/${publikationId}`);
if (!response.ok) {
throw new Error('Netzwerkantwort war nicht okay.');
}
const data = await response.json();
displayPublikationDetails(data);
} catch (error) {
console.error('Fehler beim Abrufen der Publikation:', error);
}
}
// Event-Handler für "Mehr lesen" Button
document.querySelectorAll('.more-info').forEach(button => {
button.addEventListener('click', () => {
const publikationId = button.getAttribute('data-id');
loadPublikationDetails(publikationId);
});
});
Caching
Nutze Browser-Caching, um die Daten von Publikationen zwischenzuspeichern. Bei wiederholten Anfragen können die gecachten Daten verwendet werden, anstatt sie erneut vom Server abzurufen.
// Funktion zum Abrufen der Publikationen mit Caching
async function fetchPublikationen() {
const cacheKey = 'publikationen-cache';
const cachedData = localStorage.getItem(cacheKey);
if (cachedData) {
return JSON.parse(cachedData); // Rückgabe der gecachten Daten
}
try {
const response = await fetch('https://api.example.com/publikationen');
if (!response.ok) {
throw new Error('Netzwerkantwort war nicht okay.');
}
const data = await response.json();
localStorage.setItem(cacheKey, JSON.stringify(data)); // Speichern in lokalem Speicher
return data;
} catch (error) {
console.error('Fehler beim Abrufen der Publikationen:', error);
}
}
Minimierung von HTTP-Anfragen
Kombiniere mehrere CSS- und JavaScript-Dateien zu einer einzigen Datei, um die Anzahl der HTTP-Anfragen zu reduzieren.
<!-- Kombinierte CSS-Datei -->
<link rel="stylesheet" href="styles.min.css">
<!-- Kombinierte JavaScript-Datei -->
<script src="scripts.min.js"></script>
Verwende Build-Tools wie Webpack oder Gulp, um deine CSS- und JavaScript-Dateien zu bündeln und zu minimieren.
Komprimierung
Aktiviere Gzip-Komprimierung auf deinem Webserver, um die Größe der übertragenen Daten zu reduzieren.
- In der Apache-Konfiguration aktivieren
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>
Optimierung von Bildern
Verwende komprimierte Bildformate wie WebP, um die Größe der Bilddateien zu reduzieren.
<!-- WebP-Bild verwenden -->
<img src="publikationen-image.webp" alt="Publikationsbild">
Content Delivery Network (CDN)
Nutze ein CDN, um statische Dateien wie Bilder und JavaScript von Servern näher am Benutzer bereitzustellen.
<!-- Bild von einem CDN laden -->
<img src="https://cdn.example.com/images/publikationen-image.jpg%22 alt="Publikationsbild">
Durch diese Optimierungen kann man die Ladezeiten deiner Plattform erheblich verbessern und somit die Benutzererfahrung steigern.
Ressourcenoptimierung
Um den Ressourcenverbrauch in einer Webanwendung zu optimieren, kann man verschiedene Techniken anwenden, um die Effizienz der Nutzung von CPU, Speicher und Netzwerkbandbreite zu verbessern. Hier sind einige Beispiele, wie man dies für unsere Plattform zur Veröffentlichung wissenschaftlicher Publikationen umsetzen kann:
Code-Splitting
Unterteile deinen JavaScript-Code in kleinere, nach Bedarf ladbare Teile. Das reduziert die anfängliche Ladezeit und verbessert die Leistung, da nur der benötigte Code geladen wird.
// Beispiel mit Webpack für Code-Splitting
import(/* webpackChunkName: "publikation-details" */ './publikation-details.js')
.then(module => {
const loadDetails = module.loadDetails;
loadDetails();
})
.catch(err => {
console.error('Fehler beim Laden des Moduls:', err);
});
Vermeidung von übermäßigem DOM-Manipulationen
Reduziere die Anzahl der DOM-Manipulationen, indem man Änderungen in einem Dokumentfragment vornimmt und das Fragment dann einmal in das DOM einfügt.
// Reduziere DOM-Manipulationen
const fragment = document.createDocumentFragment();
const list = document.createElement('ul');
for (let i = 0; i < 100; i++) {
const item = document.createElement('li');
item.textContent = `Publikation ${i + 1}`;
list.appendChild(item);
}
fragment.appendChild(list);
document.getElementById('publikationen-container').appendChild(fragment);
Minimierung von Berechnungen im Haupt-Thread
Verschiebe rechenintensive Aufgaben in Web Worker, um den Haupt-Thread zu entlasten und die Benutzeroberfläche reaktionsfähig zu halten.
// Haupt-Thread
const worker = new Worker('worker.js');
worker.postMessage('start');
// worker.js
self.onmessage = function(event) {
if (event.data === 'start') {
// Rechenintensive Aufgabe
let result = performHeavyComputation();
self.postMessage(result);
}
};
Ressourcenoptimierung durch Lazy Loading von Bildern
Lade Bilder nur dann, wenn sie in den Sichtbereich des Benutzers kommen, um Bandbreite zu sparen und die Ladezeiten zu verbessern.
<!-- Verwende `loading="lazy"` für Lazy Loading von Bildern -->
<img src="image.jpg" loading="lazy" alt="Publikationsbild">
Vermeidung von Redundanz bei Netzwerkanfragen
Nutze ETags und Last-Modified Header zur Validierung von Cache-Inhalten, um unnötige Netzwerkanfragen zu vermeiden.
// Beispiel für einen Server-Response mit ETag
HTTP/1.1 200 OK
ETag: "123456789"
Content-Type: application/json
// Client-seitige Validierung
fetch('https://api.example.com/publikationen', {
headers: {
'If-None-Match': '123456789' // Verwende den ETag-Wert
}
})
.then(response => {
if (response.status === 304) {
console.log('Daten nicht geändert, verwende Cache.');
} else {
return response.json();
}
});
Effiziente Datenabfragen
Wir können API-Anfragen optimieren, indem man nur die benötigten Daten abfragt und die Abfragen entsprechend filtert.
// API-Anfrage mit spezifischen Abfrageparametern
fetch('https://api.example.com/publikationen?fields=titel,abstract')
.then(response => response.json())
.then(data => {
console.log(data);
});
Optimierung der Bildgröße
Verwende Bildkomprimierung und -optimierung, um die Dateigröße zu reduzieren, ohne die Bildqualität merklich zu beeinträchtigen.
<!-- Komprimiertes Bild verwenden -->
<img src="publikationen-image-compressed.jpg" alt="Publikationsbild">
Durch diese Techniken kann man den Ressourcenverbrauch deiner Anwendung senken, die Leistung verbessern und eine flüssigere Benutzererfahrung bieten.
Bibliography
BitBucket. (2024, Juli 28). BitBucket. Retrieved from BitBucket: https://bitbucket.org
CoPilot, G. (2024, July 10). Retrieved from https://github.com/features/copilot
Eclipse Foundation. (2024, Juli 2024). Eclipse. Retrieved from Eclipse: https://www.eclipse.org
Figma. (2024, Juli 28). Figma. Retrieved from Figma: https://www.figma.com
git. (2024, Juli 28). git-scm. Retrieved from git-scm: https://git-scm.com
GitHub. (2024, Juli 2024). GitHub. Retrieved from GitHub: https://github.com
GitLab. (2024, Juli 29). GitLab. Retrieved from GitLab: https://about.gitlab.com
Google. (2024, Juli 28). Angular. Retrieved from Angular: https://angular.dev
JetBrains. (2024, Juli 28). JetBrains. Retrieved from JetBrains: https://www.jetbrains.com/idea/
Markdown. (2024, Juli 28). Markdown Guide. Retrieved from Markdown Guide: https://www.markdownguide.org
Meta. (2024, August 10). React. Retrieved from React: https://react.dev
Meta Open Source. (2024, Juli 28). React. Retrieved from React: https://react.dev
Microsoft. (2024, Juli 28). TypeScript. Retrieved from TypeScript: https://www.typescriptlang.org
Microsoft. (2024, Juli 28). VisualStudioCode. Retrieved from VisualStudioCode: https://code.visualstudio.com
OpenAI. (2024, July 10). OpenAI. Retrieved from OpenAI: https://chat.openai.com/
OpenAPI. (2024, Juli 28). OpenAPI. Retrieved from OpenAPI: https://www.openapis.org
OpenJS Foundation. (2024, Juli 28). ESLint. Retrieved from ESLint: https://eslint.org
Postman, Inc. (2024, 08 13). Postman. Retrieved from Postman: https://www.postman.com
Prettier. (2024, Juli 28). Prettier. Retrieved from Prettier: https://prettier.io
SmartBear. (2024, 08 13). SwaggerEditor. Retrieved from SwaggerEditor: https://editor.swagger.io
Swagger. (2024, Juli 28). Swagger. Retrieved from Swagger: https://swagger.io/tools/swagger-ui/
The Linux Foundation. (2024, 08 13). OpenAPI. Retrieved from OpenAPI: https://www.openapis.org/what-is-openapi
You, E. (2024, Juli 28). Vue.js. Retrieved from Vue.js: https://vuejs.org