J o: HTML und Javascript OOP

Einen wunderschönen Sonntag zusammen,

ich bin seit einigen Tagen am überlegen, ob ich die Art wie ich Javascript beim Client verwende umstrukturiere.

Derzeit:

Nach einem entsprechenden Request kommt von meinem Server ein umfangreiches Objekt mit Templates und Daten aus meiner Datenbank. Dieses ist derzeit Global an jeder Stelle verfügbar. Entsprechend der Daten gibt es dann die ein oder andere Schleife welche an ein Template die Daten übergibt und diese dann dem DOM hinzufügt. Wenn dies alles erledigt ist, werden für die entsprechenden Buttons Eventlistener gesetzt welche dann die entsprechende Funktionalität besitzen. Zudem werden zwei Funktionen initialisiert die in festen Intervallen diese Daten bearbeitet/weiterrechnen und den Inhalt der Elemente im DOM mit den neuen Daten überschreibt. Da mitunter viele gleichartige Strukturen vorhanden sind und die Daten sich Server seitig ändern können, frage ich mich ob das der geeignete Weg ist.

Konzept1:

Wenn die Daten vom Server kommen, könnte ich auch die in den Schleifen durchgeführte Funktionalität in ein Objekt auslagern. Dieses Objekt könnte im Konstruktor das Template mit den Daten dem DOM hinzufügen und direkt einen Pointer auf das gesamte Element besitzen. (Beispiel ungetestet, könnten Fehler vorhanden sein)

var objects = [];
for(i in data) {
	objects.push( new testObject( data.something[i], data.templates ) ); 
}
var testObjekt = function ( data, template ) {
	this.el = document.getElementById("something").appendChild( template );
	this.el.innerHTML = data.something;
	this.data = data;
	this.update = function ( data ) {
		this.data = data;
		this.el.innerHTML = data.something;
	}
}
  1. Frage:

Wenn objects[i].update(data) aufgerufen wird, dann muss das DOM sehr wahrscheinlich nicht nach dem richtigen Element durchsucht werden, richtig?

2.Frage:

Wie geht ihr mit Daten um, die in zwei Funktionen ständig in Intervallen genutzt oder benötigt werden? Beziehungsweise, wie können Redundanzen vermieden werden?

Konzept 2: Daten bleibt Global.

var data = {...};
var objects = [];
for(i in data) {
	objects.push( new testObject(i) ); 
}
var testObjekt = function (i) {
	this.el = document.getElementById("something").appendChild( data.template );
	this.el.innerHTML = data.something[i];
	this.update = function ( i ) {
		this.el.innerHTML = data.something[i];
	}
}

Macht das vielleicht mehr Sinn? Ist das so gängig? Oder geht das noch eleganter?

Vielen Dank schon mal und Ein schönes Restwochenende.

Gruß
Jo

  1. Hallo,

    was du machst klingt für mich stark nach dem Ansatz, den react.js verfolgt. Warum wechselst du nicht einfach dahin?

    Der wesentliche Unterschied ist, dass das Template auf client-seite gehalten wird statt im Server zu liegen - da du aber sowieso noch behaviour binden musst (deine Event-Listener) ist der Code eh abhängig vom Template. Auf dieses Feature (dynamische Templates) würde ich im Zweifel eher verzichten. Nicht, dass es mit react unmöglich wäre - nur ungewöhnlich.

    Ansonsten: zu deiner Frage 1: ja, Template und Daten an einer Stelle zu halten ist nicht unüblich. Meist sind die JS-Frameworks Komponenten-basiert. Das, was du beschreibst, wird darin üblicherweise Controller genannt.

    Frage 2: die Idee ist es meistens, einen zentralen Datenservice zu haben, auf den die Controller referenzieren. Entweder, weil die Controller nur Referenzen nutzen oder in dem du die Controller als Event-Listener auf Updates beim Daten-Service einträgst. Gibt noch andere Methoden, aber das wären zumindest bei weitverteilten Komponenten (also insb. nicht welche in Kind-/Eltern-Beziehungen) üblich. Andere Methoden sind über Event-Listening/-Publishing (würde ich meist von abraten) oder über Attribute (wenn du einen Ansatz machst, in dem die Kind-Komponenten als WebComponents [wie bei react.js, angular sind die Komponenten neue HTML-Elemente] einbindest.

    Viele Grüße Matti

    1. Guten Morgen,

      was du machst klingt für mich stark nach dem Ansatz, den react.js verfolgt. Warum wechselst du nicht einfach dahin?

      Ja, hatte ich vor ein paar Wochen auch schon überlegt aber ich bin gerade sogar dabei alle Frameworks auf ein Minimum zu reduzieren, also ich substituiere JQuery und anderes.

      Frage 2: die Idee ist es meistens, einen zentralen Datenservice zu haben, auf den die Controller referenzieren. Entweder, weil die Controller nur Referenzen nutzen [...]

      Das wäre dann ja ein Globales Objekt mit den Daten die vom Server kommen. So denke ich werde ich das auch umsetzen. Vielen Dank.

      Gruß
      Jo

      1. Hallo Jo,

        kommt drauf an. Hast Du Dich schon mit dem Modul-Pattern in JavaScript beschäftigt? Mit diesem Pattern kannst du zumindest dafür sorgen, dass die Daten nicht superglobal herumliegen, sondern nur in einem einzelnen Modul, das für ihre Verarbeitung erforderlich ist.

        Module gibt es klassisch über define-/require Funktionen (nach der Idee von CommonJS), z.B. unterstützt durch JS Libs wie require.js - aber da willst Du ja 'runter :)

        ES 2015 führt über import/export ebenfalls ein Modulsystem ein. Wenn Du das in älteren Browsern nutzen willst (insbes. IE11), brauchst Du einen Transpiler (Typescript, Traceur, Babel etc).

        Oder Du schreibst einen einfachen manuellen Modulmanager, der dann dein einziges globales Objekt sein müsste. Den lädst Du zuerst, und alle deine Module registrieren sich dort.

        Die Idee ist jedenfalls, dass jedes Modul in einer IIFE gekapselt ist und ein Objekt zurückgibt, das das Modul repräsentiert. Das kann eine Konstruktorfunktion sein, ein HTML Template oder ein Objekt mit irgendwelchen Helper-Funktionen. Irgendeine orchestrierende Komponente muss dann wissen, welches Modul welches andere Modul referenziert und stellt die Modulobjekte bereit - oder es gibt einfach einen großen Topf an vorhandenen Modulen und jedes Modul greift bei seiner Initialisierung in diesen Topf und holt sich die benötigten Modulobjekte heraus. Die Herausforderung ist dann, die richtige Initialisierungsreihenfolge zu finden.

        Rolf

        --
        sumpsi - posui - clusi
  2. Gute Idee!

    Wie geht ihr mit Daten um, die in zwei Funktionen ständig in Intervallen genutzt oder benötigt werden? Beziehungsweise, wie können Redundanzen vermieden werden?

    Ganz einfach: Die Daten werden als Eigenschaften an die Instanz gehängt. Womit sie in jeder Methode, welche die Instanz aufruft, zur Verfügung stehen, auch in den Callbackfunktionen.

    Dateiweit gibt es anstelle vieler einzelner Variablen nur die Instanz:

    var main = new Main({url:"/fm.html"});
    main.call();
    

    Was beim Entwickeln den Vorteil hat, mal eben per console.log(JSON.stringify(main,null,2)); gucken zu können, wie es um die Daten bestellt ist.

    MfG

    MfG