Archiv für Informatik

Ein einfaches JavaScript Routing

Eine vernünftige Architektur auf der Clientseite wird oft sehr vernachlässigt. JavaScript wird in der Verwendung reduziert auf seine Skript-Funktionalitäten. Dabei lässt sich durch ein paar Handgriffe eine sehr gute Architektur einbauen, die bereits ein mini-MVC Framework implementiert.

Die Grundlage dabei bilden die Routen. Eine Route repräsentiert dabei eine statische Seite unter einer URL. Der Ablauf ist folgender:

  1. Definition der Routen
  2. Der Dispatcher wird gestartet
  3. Dieser sucht für die aktuelle URL eine konfigurierte Route
  4. Der Controller wird aus der Route geholt und initialisiert
  5. Der Controller-Code wird ausgeführt

 

Definition der Routen

 

1
2
3
4
5
6
7
8
9
10
11
12
class Route {
constructor(url, controllerClass) {
this._url = url;
this._controllerClass = controllerClass;
}
matches(currentUrl) {
return currentUrl.match(this._url).length > 0;
}
getControllerClass() {
return this._controllerClass;
}
}

Diese Klasse repräsentiert eine einzelne Route. Es wird die URL als regulärer Ausdruck übergeben und die Referenz der Controller-Klasse.

Mit der Methode matches wird untersucht, ob die Route auf die URL passt.

 

Verwalten der Routen und Suchen der aktuellen Route:

 

1
2
3
4
5
6
7
8
9
const Routing = {
_routes: [],
registerRoute(route) {
this._routes.push(route);
},
getCurrentRoute(currentUrl) {
return this._routes.find((route) => route.matches(currentUrl));
}
}

Dieses Singleton Objekt verwaltet alle definierten Routen und sucht nach der ersten passenden Routendefinition zu einer URL.

 

Der Dispatcher

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Dispatcher {
constructor() {
window.addEventListener('popstate', () => this.onRouteChanged());
this.onRouteChanged();
}
onRouteChanged() {
const url = `${window.location.pathname}${window.location.hash}`;
const route = Routing.getCurrentRoute(url);

let controllerInstance = null;
if(route) {
const controllerClass = route.getControllerClass();
controllerInstance = new controllerClass();
}

const event = new Event('routeDispatched');
event.controller = controllerInstance;
window.dispatchEvent(event);
}
}

Der Dispatcher sucht für die aktuelle URL die passende Route. Wenn eine vorliegt, dann wird der Controller instanziiert und ein Event auf window getriggert. Das Event enthält die Controller-Instanz für den Fall, dass jemand den Controller benötigt. Aber vor allem lässt das Event eine asynchrone Steuerung zu.
 

Anwendungs-Beispiel

 

1
2
3
4
5
6
7
8
class ControllerA {
constructor() {
alert('It works!');
}
}

Routing.registerRoute(new Route('', ControllerA));
const dispatcher = new Dispatcher();

 

Fazit

 

Mit ein paar Handgriffen ist ein einfaches Dispatching gebaut. Natürlich fehlen noch einige Dinge; Fehlerbehandlung, eine Model- und eine View-Schicht. Wenn man weiterhin mit Promises arbeitet, kann man auf einfachem Wege asynchrone Initialisierungen implementieren. So lässt sich beispielsweise eine “initialize” Methode im Controller einbauen, die Daten asynchron vom Server lädt. Model und View Klassen lassen sich bequem über die Route hinzufügen. Man kann Basisklassen für alle Ebenen verwenden, um gemeinsame Funktionalitäten zu kapseln.

Weitere Links:

OMeta

OMeta ist ein Objekt-Orientiertes Parser Framework für PEG’s. Die Implementierung ist in diversen dynamischen Programmiersprachen verfügbar (Javascript, Python, Common Lisp, C#, Scheme, Ruby). Diese muss aber als Interpretation des Modells angesehen werden. Weiterlesen

Binär Uhr

Die moderne Uhr kann man logisch in 2 Bereiche aufteilen: Stundenzeiger und Sekundenzeiger. Der Stundenzeiger läuft dabei nach einen 12er System, der Sekundenzeiger in einem 60er System.

Weiterlesen

Constraintprogrammierung

Ein Sudoku zu lösen ist ein Unterfangen, welches durchaus einiges an Zeit beanspruchen kann. Ein Computerprogramm kann jedoch sehr schnell zu einer Lösung kommen. Gehen wir mal von den Fall aus, dass ein Programm ein neues Sudoku erstellen soll. Es gibt also keine vorausgefüllten Bereiche. Nehmen wir an die Größe des Sudoku sei 9×9 Felder.
Weiterlesen

Apfelmännchen

Das Apfelmännchen kommt aus der Familie der Fraktale, genauer der Mandelbrotmenge. Ein Fraktal definiert sich dadurch, dass es Muster besitzt, die sich innerhalb des Musters wiederfinden. Wenn man z.B.: eine Visualisierung vergrößert, finden sich die ursprünglichen Muster immer wieder – theoretisch bis ins Unendliche. In der Mathematik kann ein Fraktal z.B. durch eine Folge definiert werden.
Weiterlesen