Spiel am Rückgrat und Glut

Sie haben also die Herausforderung angenommen, sich auf der Kundenseite durchzusetzen. gut gemacht. Sie haben alle Frameworks in Betracht gezogen und sind sich nicht sicher, welches Sie wählen sollen? Du bist nicht allein. Weiter lesen.

Meine Erfahrung, wenn ich lerne, wie man clientseitige Apps schreibt, erweist sich als steil und hart. Es ist nicht einfach, sich bewusst für die Verwendung zu entscheiden MV * auf dem Client für jemanden, der JavaScript geschrieben hat, basierend auf jQuery und seinen Plugins. Dies ist ein völlig neues Paradigma. Es erfordert grundlegende Programmierkenntnisse und ein beträchtliches Verständnis für das Design von JavaScript (der Sprache). Wenn sich Ihre Erfahrung auf meine bezieht, dann lesen Sie weiter!

Ich werde die Hauptunterschiede zwischen zwei der beliebtesten JavaScript-Client-Frameworks erläutern: Backbone.js und Ember.js. Jedes dieser Tools hat Stärken sowie Schwächen, die Ihnen helfen könnten, eine durchdachtere Entscheidung zu treffen.

Haftungsausschluss: Als Softwareexperten müssen wir uns mit der Meinungsvielfalt auseinandersetzen. Backbone und Ember sind Ergebnisse von meinten und erfahrenen Fachleuten wie Sie und ich. Ein Werkzeug ist nicht besser als das andere; Sie dienen nur verschiedenen Menschenmassen und lösen verschiedene Probleme. Danke Trek für den guten Rat.


Die Philosophie

Backbone ist viel leichter zu erlernen als Ember.

Zuallererst müssen Sie verstehen, dass Backbone und Ember vor allem etwas unterschiedliche Menschenmengen bedienen. In Bezug auf die Komplexität ist Backbone viel einfacher zu erlernen als Ember. Man sagt jedoch, dass, wenn man Ember lernt, es kaum komplexer wird. Nimm Treks Wort dazu. Wenn Sie gerade mit etwas echtem JavaScript beginnen, ist Backbone vielleicht Ihr Werkzeug. Wenn Sie jedoch wissen, dass Sie mit mehr als nur einem oder zwei einfachen Anwendungsfällen zu tun haben werden, könnten Sie Ember bevorzugen.

Rückgrat

Jeremy Ashkenas baute Backbone, damit es möglich wäre nimm die Wahrheit aus dem DOM. Was er damit meint, ist: Was auch immer Sie mit jQuery / Mootools / Prototype gemacht haben, könnte und sollte besser in reine JavaScript-Strukturen extrahiert werden - Objekte, wenn Sie so wollen. Anstatt zu verwenden DOM Elemente, um Ihre Geschäftselemente und Ihr Verhalten zu definieren, lädt Backbone Sie ein, es andersherum zu machen. JavaScript-Objekte sind der Kern und der DOM ist nur eine Darstellung dieser Daten.

Mit Backbone haben Sie einige Aussagen gemacht:

  1. Daten liegen in JavaScript-Objekten, nicht im DOM
  2. Die Ereignisbehandlung liegt in JavaScript-Objekten und nicht in jQuery-Ereignisbindungen
  3. Die Art und Weise, wie Sie Daten auf einem Backend-Server speichern, geschieht über die Objekte, die die Daten enthalten

Sie erhalten vollständige Kontrolle über die Art und Weise, wie Sie Ihre App erstellen. Backbone sollte Ihnen eine grundlegende Möglichkeit bieten, Modellobjekte zu entwerfen und wie diese über Ereignisbindungen miteinander interagieren.

Rendering HTML zum DOM liegt in Ihrer Verantwortung. Sie können eine beliebige Template-Engine auswählen: Moustache, DoT, Lenker, Unterstrich usw. Das Backbone enthält a Aussicht Prototyp, der die Verantwortung hat, das zu artikulieren DOM und dein JavaScript-Kern.

Glut

Als Tilde mit dem Bau von Ember begann, tat dies ein weit herausfordernderes Ziel: to bieten standardkonventionen in der clientseitigen entwicklung und vermeiden so viel boilerplate wie möglich. Das Ergebnis ist ein viel ehrgeizigerer Rahmen, der auf eine vorhersagbare Architektur und eine stetige Entwicklung abzielt.

Ember teilt einige Gemeinsamkeiten mit Backbone in der Art und Weise, wie es versucht, Daten und Verhalten aus dem Internet zu ziehen DOM durch die Bereitstellung erweiterbarer JavaScript-Prototypen, dies jedoch auf eine ganz andere Weise als Backbone.

Glut steht auf:

  1. Zweiwege-Datenbindung: Objekte in Ember können Bindungen untereinander registrieren. Auf diese Weise wird die andere automatisch aktualisiert, wenn sich eine gebundene Eigenschaft ändert.
  2. Berechnete Eigenschaften: Wenn Sie eine Eigenschaft haben möchten, die auf einer Funktion beruht, können Sie diese erstellen und eine von dieser Funktion berechnete Eigenschaft zuweisen.
  3. Automatische Aktualisierung von Vorlagen: Wenn ein Objekt in Ihrer App aktualisiert wird, spiegeln alle aktuell auf dem Bildschirm angezeigten Ansichten, die an dieses Objekt gebunden sind, die Änderung automatisch und ohne Zwischenablage wieder.

Die DOM - Ansichten

Sowohl Backbone als auch Ember haben gemeinsame Schlüsselkonzepte, wie z Ansichten. Sie vertreten beide DOM Kommunikation jeweils. Die Art und Weise, wie sie dieses Konzept erreichen, ist jedoch etwas anders.

Ich verwende den Todo-Anwendungsfall für die folgenden Beispiele, der vom TodoMVC-Showcase inspiriert wurde.

Rückgrat

Eine Backbone-Ansicht könnte etwa so aussehen:

var TaskView = Backbone.View.extend (tagName: "li", template: "task-template", render: function () // Ihr Code, den Sie hier rendern möchten., events: "click .mark-done") : "mark_as_done", "change .body": "update_body", mark_as_done: function () / * code here * /, update_body: function () / * code here * /);

Dies ist einfach die Definition Ihrer Ansicht. Sie müssen eine Instanz instanziieren, wenn Sie möchten, dass sie auf der Seite angezeigt wird. So etwas wird den Trick tun:

var task_view = neue Aufgabe (model: task_model); $ ("body"). append (task_view.el);

Beachten Sie, dass wir ein Modell übergeben, damit Sie einen Verweis auf das Datenobjekt beibehalten können, das die Vorlage enthält. Das Vorlage Die Eigenschaft in der Ansicht kann verwendet werden, um über eine Kennung eine äußere Vorlage aufzurufen. Ich habe in der Vergangenheit so etwas verwendet:

var TaskView = Backbone.View.extend (template: "# task-template"), render: function () this. $ el.html (Mustache.render ($ (this.template) .html ())). model); // snip);

Glut

Glut hat eine andere Sichtweise. Tatsächlich heißt es in der Konvention, dass Ansichten mit Steuerungen und nicht direkt mit Modellen kommunizieren sollten. Dies ist eine gute Vorgehensweise, wenn Sie eine stabile Architektur verfolgen möchten. Ich werde das Beispiel für dieselbe Ansicht erklären:

var TaskView = Ember.View.extend (templateName: "task-template", mark_as_done: function () / * code here * /, update_body: function () / * code here * /);

Das ist es. Aber wo ist das ganze Rendering? Nun, Ember hebt die Kesselplatte für Sie an. Sagen Sie einfach, was die Vorlage ist, der Controller, der das Datenobjekt enthält, und dann müssen Sie es nur an das anhängen DOM.

var task_view = TaskView.create (controller: task_controller // Ember.ObjectController); task_view.append ();

Wenn Sie eine neue Ansichtsinstanz erstellen, wird der Inhalt des Controllers gebunden Ember.Object oder eine Liste davon) zur Ansicht. Wenn Sie sich entscheiden, die Ansicht an die anzuhängen DOM, Es wird die Vorlage nachschlagen und die generierte Markierung für Sie platzieren.

Gedanken

Das Rückgrat ist expliziter und weniger magisch.

Das Rückgrat ist expliziter und weniger magisch. Sie erstellen eine Aussicht, Geben Sie an, welche Vorlage verwendet werden soll und wie, registrieren Sie die Ereignisse und machen Sie, was Sie tun müssen. Ihnen gehört die Seite. Dies ist ein großartiger Start für alle, die aus einem jQuery-Hintergrund kommen. Wenn jedoch etwas aktualisiert werden muss DOM, Sie werden sich einer Boilerplate stellen.

Mit Ember werden Updates automatisch durchgeführt. Sie sagen, um welche Vorlage es sich handelt, und Ereignisrückrufe sind Funktionen innerhalb des Ansichtsobjekts. Bei jeder Aktualisierung eines Objekts wird die Seite automatisch von der Ansicht aktualisiert.

Einige übliche Ereignisbindungen sind in Ember integriert, andere müssen in die Vorlage eingefügt werden. Es ist gut für diejenigen, die aus einer Backend-Perspektive kommen, da sie die Boilerplate erheblich reduzieren.


Die Datenmodelle

Modelle in Backbone und Ember sind sehr ähnlich. Sie enthalten Informationen zu einer Geschäftseinheit.

Rückgrat

Ein Beispiel für ein Backbone-Modell sieht folgendermaßen aus:

var TaskModel = Backbone.Model.extend ();

Mit dieser einfachen Codezeile haben Sie ein Arbeitsmodell mit SICH AUSRUHENKommunikation integriert. Sie erhalten Methoden wie sparen um die Daten zu erhalten und holen um es kostenlos zu laden; Es ist kein Plugin erforderlich. Die Validierung ist auch in die Art und Weise integriert, in der Daten gespeichert werden, indem a bereitgestellt wird bestätigen callback, der einen booleschen Wert zurückgibt, der den Datensatz anweist, gespeichert zu werden oder nicht. Die Implementierung der Validierung muss noch vom Entwickler durchgeführt werden.

Um eine neue Aufgabe zu erstellen, instantiieren Sie eine neue TaskModel.

var task = new TaskModel (body: "Mow the lawn", done: false);

Sie können so viele Attribute einfügen, wie Sie möchten, da die Attributliste der Aufgabe nicht streng ist Schemalos). Sie können noch ein einstellen Standardeinstellungen Eigenschaft bei der Erweiterung Rückgrat.Modell.

Glut

Bei Ember gibt es keine Modelle, nur Objekte. Es könnte ungefähr so ​​aussehen:

var TaskObject = Ember.Object.extend ();

Ähnlich wie bei Backbone müssen Sie von erweitern Ember.Object eine Objektklasse erstellen. Es erbt alle grundlegenden Funktionen für eine Klasse mit Callbacks, wenn diese unter anderem geändert, erstellt und gelöscht wird. Es hat jedoch keine Backend-Kommunikation außerhalb der Box. Ember.Data wird als Erweiterung von entwickelt Ember.Object durch das Ember-Kernteam, um dieses Bedürfnis zu erfüllen. Es ist bereits verwendbar, aber nicht stabil, soweit die Dokumentation dies sagt.

Glutobjekte gelten auch als Schemalos. Um Standardwerte in Ember-Objekte einzufügen, erweitern Sie Ember.Object indem Sie ein Objekt mit beliebig vielen Attributen übergeben.

var TaskObject = Ember.Object.extend (body: "Mow the lawn", erledigt: false);

Gedanken

Das Backbone hat eine konsolidierte Methode zum Synchronisieren mit einer Persistenzschicht SICH AUSRUHEN und das ist eine gute Versammlung dort. Es ist eine Sache weniger, die Sie konfigurieren müssen, um mit einem Backend-Server arbeiten zu können.

Ember arbeitet daran, etwas zu machen Ember.Data bereit für die Produktion, und es sieht vielversprechend aus. Die Besonderheit von Ember-Objekten mit Zwei-Wege-Bindungen macht es jedoch leicht, Verbindungen zwischen Objekten herzustellen.

An diesem Punkt Ihres Lesens haben Sie einen Wendepunkt zwischen der Stabilität von Backbone bei der Kommunikation mit dem Backend-Server und den Bindungen von Ember. Was für Sie am wichtigsten ist, sollte Ihre Entscheidung bestimmen.


Die Leim - Controller

An dieser Stelle gehen die Rahmenbedingungen auseinander. Sie haben eine große konzeptionelle Lücke beim Zusammenkleben von Dingen in Ihrer App. Während Backbone so einfach und flexibel wie möglich bleiben will, opfert Ember die Codebase-Größe für eine bessere Architektur. Es ist wirklich ein Kompromiss.

Warnung: Die folgenden Beispiele enthalten keine Beispiele für HTML-Vorlagen.

Rückgrat

Wie ich bereits erwähnt habe, zielt Backbone auf Einfachheit, die sich in Flexibilität umwandelt, und erreicht diese Eigenschaften genau das Fehlen einer Controller-Klasse. Der größte Teil des Arbeitspferdes verteilt sich auf Ansichten, Sammlungen, Modelle und den Router (falls Sie sich für die Verwendung von Backbone entscheiden) Router).

In Anbetracht einer Liste von Aufgaben, die verwaltet werden müssen, ist Folgendes erforderlich:

  • EIN Sammlung um die Aufgaben zu speichern.
  • EIN Modell um die Informationen einer Aufgabe zu speichern.
  • EIN Aussicht um die Sammlung darzustellen.
  • Ein weiterer Aussicht jede Aufgabe darstellen.
  • EIN Router URLs verwalten.

Die meisten Anwendungslogiken werden in den Ansichten angezeigt, da sie Modelle mit der verbinden DOM. Es gibt keine klare Unterscheidung der Verantwortlichkeiten, da die Ansicht alles tut. Dies kann für kleine Anwendungen nützlich sein, die keine solide Architektur erfordern.

Um eine Liste mit Aufgaben anzuzeigen, würde am Ende Folgendes angezeigt werden:

Sammlung

var TaskList = Backbone.Collection.extend (model: Task);

Modell

var TaskModel = Backbone.Model.extend ();

Ansichten

var TaskListView = Backbone.View.extend (render: function () this. $ el.empty (); für (_i = 0, _i.) < this.collection.length; _i++)  var task = this.collection.models[_i]; this.$el.append(this.renderItem(task));  var tasks = this.$el.html(); this.$el.html(Mustache.to_html(template,  tasks: tasks, no_tasks: !this.collection.length )); , renderItem: function(task)  var view = new Row( model: task ); var el = view.render(); return el.el; , );
var TaskView = Backbone.View.extend (tagName: "tr", render: function () this. $ el.html (M.to_html (template, this.model.attributes)); zurückgeben;);

Router

var Router = Backbone.Router.extend (initialize: function () this.tasks = neue TaskList; this.view = neue TaskListView (collection: this.tasks);; routet: "": "task_list" ,, task_list: function () this.view.render (); $ (". bucket: first"). html (this.view.el);, start: function () Backbone.history.start ( pushState: true, root: "/ tickets /"););

Beachten Sie, dass die Sammlung keine eigene Vorlage hat. Es delegiert vielmehr an eine einzelne Aufgabenansicht, die gerendert und an das Endergebnis angehängt wird, das auf der Seite angezeigt wird.

Glut

Die Anzahl der Klassen, die für dasselbe Setup erforderlich sind, ist etwas größer.

  • Anstelle einer Sammlung, du hättest eine ArrayController, das funktioniert sehr ähnlich.
  • Sie hätten ein Extra ObjectController für die Verwaltung einer einzelnen Aufgabe.
  • Anstelle einer Modell, du hättest eine Objekt / DS.Model, die arbeiten gleichermaßen.
  • Sie hätten die gleiche Art von Aussichts.
  • EIN Router ist auch für die Verwaltung von URLs verantwortlich.

Sie denken vielleicht, dass sich die beiden Rahmen nicht zu sehr unterscheiden. Es ist ziemlich verlockend, aber es stimmt nicht genau. Einige besondere Unterschiede sind:

  1. Der Controller ist für die Interaktion mit den Datenobjekten verantwortlich, nicht für die Ansicht.
  2. Die Ansichten sind für den Umgang mit dem verantwortlich DOM, nicht der Controller.
  3. Die Ansichten kommunizieren mit der Steuerung, nicht direkt mit den Datenobjekten.
  4. Die Daten, aus denen die Ansichtsvorlage gespeist wird, sind tatsächlich eine Bindung an die Daten des Controllers.
  5. Der Router ist eher ein Staatsmanager, Dazu gehört viel mehr als der Umgang mit URLs.

Die Trennung der Bedenken ist auf lange Sicht gut. Controller verarbeitet Daten, Ansichten behandeln die DOM, Zeitraum. Diese Art der entkoppelten und zusammenhängenden, plattenlosen Konstruktion ermöglicht eine gezieltere Testbarkeit.

Die Implementierung zum Anzeigen der gleichen Aufgabenliste würde in Anbetracht einer vollständigen Ember-Anwendung etwa wie folgt aussehen:

Anwendungsstammarchitektur

window.App = Ember.Application.create (); App.ApplicationController = Ember.ObjectController.extend (); App.ApplicationView = Ember.View.extend (templateName: "application");

Objekt

App.Task = Ember.Object.extend ();

Controller

App.TasksController = Ember.ArrayController.extend (content: []);

Aussicht

App.TasksView = Ember.View.extend (templateName: "meine-Liste");

Router

App.Router = Ember.Router.extend (root: Ember.Route.extend (index: Em.Route.extend (route: '/', connectOutlets: function (router) router.get ('applicationController') .connectOutlet ('Aufgaben');));

In Embers Fall wird nicht viel darüber gesagt, wie Dinge im Inneren gemacht werden. Die gesamte Boilerplate wird entfernt, sodass Sie sich auf das konzentrieren können, was in Ihrer App wirklich wichtig ist: Sie definieren ein Aufgabenobjekt, einen Aufgabenlistencontroller mit einem Array, das als Array bezeichnet wird Inhalt, Ihre Ansicht und der Router kombiniert sie einfach alle und fügt sie in die Seite ein.

Gedanken

Nachdem er erkannt hat, wie Ember wirklich funktioniert, wird es befreiend.

Wie zu erwarten, war dieses Segment in beiden Frameworks am schwersten zu erfassen. Das Rückgrat war definitiv leichter zu erlernen und seine Flexibilität gibt die Kontrolle über die Art und Weise der Objekte und DOM interagieren. Dies kann für Sie von Vorteil sein, wenn Sie diese Flexibilität wirklich benötigen, aber dennoch eine Struktur für die Logik Ihrer App auf der JavaScript-Seite beibehalten möchten.

Was Ember angeht, könnte seine atemberaubende Umsetzung zunächst unheimlich sein. Nachdem er jedoch erkannt hat, wie Ember wirklich funktioniert, wird er befreiend. Alle Konventionen, die das Framework für Sie festlegt, befreit Sie von Boilerplate und Konfiguration, sodass Sie sich auf Ihre App konzentrieren können. Dies ist ähnlich wie bei Rails für die Entwicklung von Servern, die so viel Aufmerksamkeit auf sich zog.


Was unterscheidet sie??

Ember sollte die üblichen Belastungen der JavaScript-Entwicklung im Browser aufheben.

Bis jetzt war es der springende Punkt, die beiden Werkzeuge zu zeigen, um ihren einzigen und edlen Zweck anzuerkennen: das Delegieren Leistung auf die Client-Seite, sowohl durch die Struktur als auch durch die Methode.

Die Hauptstärke des Backbones ist definitiv der KISS-Ansatz. Es gibt Ihnen das Minimum, um das loszulassen DOM Als der wichtigste Unterstützer Ihrer App können Sie echte JavaScript-Objekte verwenden, die getestet und ordnungsgemäß entworfen werden können.

Backbone wird mit Sammlungen, Modellen, Ansichten und dem Router sowie anderen kleinen Dienstprogrammen geliefert. Sie können mit ihnen machen, was Sie möchten.

Ember hingegen wurde mit einer anderen Denkweise erstellt, da es auf eine viel konventionellere und meinungsmäßigere Art der Erstellung von Web-Apps abzielt. Es behandelt eine Reihe allgemeiner Probleme wie Boilerplate, Datenbindung und DOM Sie müssen sich also nicht von Anfang an um sie kümmern. Ember sollte die üblichen Belastungen der JavaScript-Entwicklung im Browser aufheben.

Ember ist vollgepackt mit Objekten, Controllern, Ansichten zur automatischen Aktualisierung, Zustandsmaschinen, Bindungen, Beobachtern und einem Router (der auch eine Zustandsmaschine ist), die alle mit einer guten Portion Konventionen beschworen werden. Sie haben bereits eine Architektur entworfen und können sofort arbeiten, ohne den Fokus zu verlieren.


Fazit

Beachten Sie die Lernlücke. Ihre Erfahrung und Ihr kulturelles Erbe bestimmen maßgeblich, wie schnell Sie sich dem Kunden anschließen. Wenn Sie Angst haben, was zu tun ist oder was Sie auswählen sollen, habe ich einen Nerv getroffen, und das ist gut! Möchten Sie eine gute Antwort auf die Wahl haben? Beide.

Es geht nur um das JavaScript

Wenn Sie sich nicht sicher sind, wie jQuery seine ganze Magie vollbringt, lernen Sie Backbone. Es ist einfacher zu beginnen und die Dokumentation ist einfach zu lesen und zu verstehen. Wenn Sie fertig sind, bauen Sie etwas auf. Mach dich schmutzig. Überprüfen Sie diese Tutorials, wenn Sie Hilfe benötigen.

Wenn Sie sich noch im Dunkeln befinden, lesen Sie die Einträge von Yehuda Katz zur Funktionsweise von JavaScript.

Sobald Sie eine bessere Vorstellung davon bekommen, wie JavaScript als Sprache funktioniert, werden Sie ein besseres Verständnis davon bekommen wie die Objekte miteinander interagieren. Wenn Sie dies tun, gehen Sie für Ember. Es ist zunächst komplizierter, aber gib nicht auf. Beginnen Sie mit dem Lesen der Dokumente und der Handbücher. Bevor Sie sich die Hände schmutzig machen, sollten Sie den Blogeintrag von Trek Glowacki überprüfen.

Mein Fazit

Ich persönlich neige zu Ember; Ich genieße die Robustheit auf Makroebene und bevorzuge auch die Konventionen. Backbone ist ein flexibleres und einfacheres Werkzeug für kleinere Apps oder kleine Funktionen in einer vorhandenen App.

Ich lerne immer noch beides und habe einige Herausforderungen zu meistern:

  • Automatische Tests: wie sie durchgeführt werden und welche Testsuite besser ist. Qunit oder Jasmin? Kopfloser (denkender PhantomJS), Knoten- oder Browsertestläufer? Noch nicht sicher.
  • Datei-Uploads
  • Internationalisierung

Was halten Sie von diesem ganzen Debakel? Hast du eine Herausforderung? Probleme oder Hindernisse? Gib mir Bescheid!