Die 8 häufigsten Fehler, die Backbone.js-Entwickler machen

Veröffentlicht: 2022-03-11

Backbone.js ist ein minimalistisches Framework, das darauf abzielt, einen einfachen Satz von Datenstrukturen und Funktionen bereitzustellen, mit denen Sie das Front-End einer strukturierten Webanwendung erstellen können. Die Komponenten von Backbone.js bieten standardmäßig eine intuitive Umgebung, mit der Sie möglicherweise bereits vertraut sind, wenn Sie mit Modellen und Ansichten im Backend arbeiten. Modelle und Sammlungen in Backbone.js sind einfach, aber sie verfügen über einige sehr nützliche Funktionen, z. B. die Option, sie einfach in REST-JSON-APIs zu integrieren. Sie sind aber auch flexibel genug, um sich nahezu jedem Praxiseinsatz anpassen zu können.

In diesem Backbone.js-Tutorial werfen wir einen Blick auf einige häufige Fehler, die häufig von freiberuflichen Entwicklern gemacht werden, die ihren ersten Versuch unternehmen, Backbone.js zu lernen, und Möglichkeiten, sie zu vermeiden.

Fehler Nr. 1: Ignorieren des Arsenals an Backbone.js-Funktionalitäten

Backbone.js mag ein minimalistisches Framework sein, aber es bietet (zusammen mit Underscore.js) eine Fülle von Features und Funktionalitäten, die die grundlegendsten und einige der kritischsten Anforderungen, die bei der Entwicklung einer modernen Webanwendung auftreten, problemlos abdecken können. Ein häufiger Fehler, den Anfänger-Entwickler oft machen, ist, dass sie Backbone.js für ein weiteres MVC-ähnliches Client-Framework für das Web halten. Obwohl dieser Abschnitt über etwas sehr Offensichtliches spricht, ist es bei Backbone.js ein wirklich kritischer Fehler, das Framework nicht gründlich zu untersuchen. Das Framework mag klein sein, aber das macht es zu einem großartigen Kandidaten für diese gründliche Erkundung. Vor allem der kleine und schön kommentierte Quellcode.

Backbone.js bietet das absolute Minimum, das erforderlich ist, um Ihrer Webanwendung die Struktur zu geben, von der sie profitieren kann. Mit seiner Erweiterbarkeit und einer Fülle von Plugins kann das Lernen von Backbone.js verwendet werden, um einige erstaunliche Webanwendungen zu erstellen. Einige der offensichtlichsten Merkmale von Backbone.js werden durch Modelle, Sammlungen und Ansichten offengelegt. Router- und Verlaufskomponenten bieten einen einfachen, aber eleganten Mechanismus zur Unterstützung des clientseitigen Routings. Obwohl Underscore.js eine Abhängigkeit von Backbone.js ist, ist es ziemlich gut in das Framework integriert, da sowohl Modelle als auch Sammlungen stark von diesem erstaunlichen Dienstprogrammgürtel für JavaScript profitieren und auch zu Ihrer Verfügung stehen.

Der Quellcode des Frameworks ist so gut geschrieben und kommentiert, dass man ihn wahrscheinlich bei einer Tasse Kaffee lesen könnte. Anfänger können sehr vom Lesen der Quellanmerkungen profitieren, da sie viel über die interne Funktionsweise des Frameworks lernen und auch eine Reihe von Best Practices in Bezug auf JavaScript übernehmen können.

Fehler Nr. 2: Modifizieren von DOM als direkte Reaktion auf willkürliche Ereignisse

Wenn wir Backbone.js zum ersten Mal lernen, neigen wir dazu, Dinge nicht so zu tun, wie von Backbone.js empfohlen. Zum Beispiel neigen wir dazu, Ereignisse zu handhaben und Updates so anzuzeigen, wie wir es mit jQuery auf einfachen Websites tun würden. Backbone.js soll Ihrer Webanwendung durch die richtige Trennung von Anliegen eine starre Struktur geben. Was wir mit Backbone.js oft tun, ist, eine Ansicht als Reaktion auf beliebige DOM-Ereignisse zu aktualisieren:

 var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { $(event.target).toggleClass('btn-play btn-pause') } }, // ... })

Dies ist etwas, das um jeden Preis vermieden werden sollte. Es kann möglich sein, obskure Beispiele zu finden, wo dies sinnvoll ist; aber in den meisten Fällen gibt es viel bessere Möglichkeiten, dies zu tun. Eine Möglichkeit, die ich hier möglicherweise veranschaulichen könnte, besteht darin, das Modell zu verwenden, um den Zustand des Audioplayers zu verfolgen, und diese Zustandsinformationen zu verwenden, um die Schaltfläche (oder genauer gesagt ihre Klassennamen) zu rendern:

 var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function(event) { this.model.set('playing', !this.model.get('playing')) } }, initialize: function() { this.listenTo(this.model, 'change', this.render) this.render() }, // ... })
 <button class=”btn btn-<%- playing ? 'pause' : 'play' %>”></button>

Es kann seltene Situationen geben, in denen eine direkte Manipulation des DOM durch die Event-Handler sinnvoll ist, aber die Kosten, die mit der Verwaltung komplexer DOM-Manipulationen durch Event-Handler verbunden sind, lohnen sich fast nie. Dies ist etwas, das Backbone.js lösen möchte. Backbone.js für so etwas zu verwenden, ist ein Fehler.

Fehler Nr. 3: Unterschätzung der Rendering-Kosten

Da Backbone.js es sehr einfach macht, das DOM nach Belieben oder als Reaktion auf Ereignisse zu rendern und erneut zu rendern, übersehen wir oft, wie stark sich dies auf die Gesamtleistung der Webanwendung auswirkt. Es gibt viele Möglichkeiten, wie wir die Rendermethode für unsere Ansichten durcheinanderbringen können. Oft scheint dies nicht viel zu sein, da moderne Webbrowser zu hochleistungsfähigen Softwarekomponenten werden. Aber wenn die Webanwendung wächst und die Datenmenge wächst, die sie verarbeitet, wird der Leistungsabfall immer deutlicher.

Wir können dies anhand eines erfundenen Beispiels in Aktion sehen, in dem wir mit einer kleinen Sammlung von Modellen beginnen und diese in eine Listenansicht rendern:

 var AudioPlayerPlaylist = Backbone.View.extend({ template: _.template('<ul> <% _.each(musics, function(m) { %> <li><%- m.title %></li> <% }) %> </ul>'), initialize: function() { this.listenTo(this.collection, 'add', this.render) }, // ... })

In diesem Backbone.js-Beispiel rendern wir jedes Mal neu, wenn ein Modell zur Sammlung hinzugefügt wird. Das wird gut funktionieren. Da das „add“-Ereignis jedoch jedes Mal ausgelöst wird, wenn ein Modell zur Liste hinzugefügt wird, stellen Sie sich vor, Sie würden eine große Liste von Modellen vom Server abrufen. Die Rendermethode wird mehrmals hintereinander aufgerufen, einmal für jedes Modell in der Antwort vom Server. Ein ausreichend großes Modell reicht aus, um Ihre Anwendung ins Stottern zu bringen und die Benutzererfahrung zu ruinieren. Manchmal reicht eine kleine Antwort aus, abhängig von der Komplexität der gerenderten Ansicht.

Eine sehr schnelle Lösung hierfür besteht darin, die Render-Methode einfach nicht für jedes einzelne Modell aufzurufen, das hinzugefügt wird. In Situationen wie diesen werden Modelle im Stapel hinzugefügt, und Sie können tatsächlich etwas tun, damit die Rendermethode nur dann ausgelöst wird, wenn sie aufgerufen, aber nicht innerhalb einer bestimmten Zeit erneut aufgerufen wird. Die Abhängigkeit von Backbone.js Underscore.js enthält dafür eine praktische Utility-Funktion: „_.debounce“. Alles, was Sie brauchen, um davon zu profitieren, ist, die JavaScript-Zeile für die Ereignisbindung wie folgt zu ändern:

 this.listenTo(this.collection, 'add', _.debounce(_.bind(this.render), 128))

Dadurch wird der Ereignis-Callback jedes Mal ausgelöst, wenn das „add“-Ereignis eintritt, es wird jedoch 128 Millisekunden nach dem letzten Ereignis gewartet, bevor die Render-Methode tatsächlich aufgerufen wird.

In den meisten Fällen wird dies als schnelle Lösung angesehen. Tatsächlich gibt es geeignetere Möglichkeiten, Render-Thrashing zu vermeiden. Entwickler hinter Trello haben einmal einen Blogbeitrag geschrieben, in dem sie über ihre Erfahrungen und ihren Ansatz zur Verbesserung der Rendering-Leistung bei der Verwendung von Backbone.js diskutierten.

Fehler Nr. 4: Ereignis-Listener über ihre Verwendung hinaus gebunden lassen

Unbenutzte Ereignis-Listener gebunden zu lassen, ist wahrscheinlich etwas, das passieren kann, unabhängig davon, welches JavaScript-Framework Sie verwenden, oder ob Sie überhaupt eines verwenden. Auch wenn Backbone.js es einfach macht, dieses Problem zu vermeiden, ist es sicherlich ein Fehler, potenzielle Löcher für einfache Speicherlecks in Ihrer Webanwendung zu hinterlassen. Die „Event“-Komponente von Backbone.js ist sicherlich eine ziemlich ordentliche Implementierung. Es ermöglicht JavaScript-Objekten, ereignisbasierte Funktionen einfach zu implementieren. Da Views der Ort sind, an dem der Großteil unserer Ereignisnutzung normalerweise stattfindet, ist es dort leicht, diesen Fehler zu machen:

 var AudioPlayerControl = Backbone.View.extend({ initialize: function() { this.model.on('change', _.bind(this.render, this)) // ... }, // ... })

Die Ereignisbindungszeile in diesem Codeschnipsel unterscheidet sich nicht sehr von der im ersten Beispiel. Alles, was wir hier getan haben, ist, dass wir „this.listenTo(this.model, …)“ in „this.model.on(…)“ geändert haben. Da wir aus unserer Erfahrung mit einigen anderen JavaScript-Frameworks und -Bibliotheken sehr an den „.on()“-Aufruf für die Ereignisbindung gewöhnt sind, neigen wir häufig dazu, die „.on()“-Aufrufe zum Binden zu verwenden, wenn wir Backbone.js verwenden Veranstaltungen. Dies wäre in Ordnung gewesen, nur wenn wir uns die Mühe gemacht hätten, „.off()“ aufzurufen, um die Event-Handler zu entbinden, wenn sie nicht mehr benötigt werden. Aber wir tun das selten, und es endet damit, dass es zu Speicherlecks kommt.

Backbone.js bietet eine einfache Möglichkeit, dieses Problem zu lösen. Dies geschieht durch die Verwendung der Methode „object.listenTo()“. Dadurch kann das Objekt, für das Sie „listenTo()“ aufrufen, nachverfolgen, auf welche Ereignisse es wartet, und es ist auch einfach, alle diese Ereignisse auf einmal zu entbinden. Ansichten zum Beispiel hören automatisch nicht mehr auf alle gebundenen Ereignisse, sobald Sie „remove()“ darauf aufrufen.

Fehler Nr. 5: Monolithische Ansichten erstellen

Wenn Sie darüber nachdenken, bietet der Minimalismus von Backbone.js eine enorme Flexibilität bei der Gestaltung des Front-Ends Ihrer Webanwendung. Da Modelle, Sammlungen und Ansichten die Bausteine ​​Ihrer Komponenten sind, ist es wichtig, dass Sie sie so einfach und spezifisch wie möglich halten. Meistens sind es Ansichten, die in Bezug auf den Code zum schwersten Aspekt Ihrer Webanwendung werden. Aber es ist wirklich wichtig, dass Sie nicht am Ende riesige monolithische Ansichten erstellen, die am Ende versuchen, alles zu tun, was Ihre Anwendung zu bieten hat. Anstatt eine riesige „AudioPlayer“-Ansicht mit all der darin vollgestopften Logik zu erstellen, teilen Sie sie in eine Reihe logischer Ansichten auf, z. B. eine Ansicht für die Wiedergabeliste, eine Ansicht für die Steuerelemente, eine Ansicht für den Visualizer und so weiter. Welche Art von Granularität Sie sicherstellen möchten, hängt wahrscheinlich von der Anwendung ab, die Sie erstellen möchten.

Denn mit granularen Ansichten, bei denen jede Ansicht etwas Bestimmtes tut und es richtig macht, wird die Entwicklung einer Webanwendung mit Backbone.js zum Kinderspiel. Ihr Code sollte besser wartbar und in Zukunft einfach zu erweitern oder zu ändern sein. Dann gibt es noch das andere Extrem, wo man am Ende übertreibt. Backbone.js-Ansichten sind so konzipiert, dass Sie bequem mit einem Modell oder einer Sammlung arbeiten können, und dies kann wahrscheinlich als Hinweis darauf dienen, wie Sie Ihre Anwendung strukturieren sollten. Ian Storm Taylor hat in seinem Blog einige wertvolle Ideen geteilt, die Sie beim Implementieren von Ansichten wahrscheinlich im Hinterkopf behalten sollten.

Fehler Nr. 6: Nicht erkennen, dass Backbone.js an Nicht-RESTful-APIs angepasst werden kann

Backbone.js funktioniert standardmäßig mit JSON-basierten RESTful-APIs. Alles, was Sie dafür brauchen, ist jQuery (oder etwas, das ein Drop-in-Ersatz dafür ist, wie z. B. Zepto). Backbone.js ist jedoch extrem erweiterbar. Tatsächlich kann Backbone.js angepasst werden, um andere Arten von APIs und sogar andere Arten von Codierungsformaten zu verwenden.

Die Komponente von Backbone.js, die sich mit der Interaktion des Frontends mit den Backend-Diensten befasst, ist „Sync“. Diese Komponente stellt eine Reihe von Attributen bereit, die Sie einfach überschreiben können, um die Art der Interaktion von Backbone.js mit den API-Endpunkten anzupassen. Tatsächlich ist es auch möglich, den Standard-Synchronisierungsmechanismus durch etwas zu ersetzen, das gelinde gesagt nicht so traditionell ist, wie z. B. die Verwendung von localStorage zum Persistieren von Daten anstelle von Back-End-Diensten.

Es gibt zahlreiche Plugins, die es einfach machen, das Synchronisierungsverhalten von Backbone.js anzupassen. Mit einem Plug-in namens Backbone.dualStorage können Sie beispielsweise sowohl die Back-End-Dienste als auch localStorage verwenden, um Daten zu speichern. Wenn Ihre Anwendung offline geht, verwendet das Plug-in localStorage, um Anfragen aus zwischengespeicherten Daten weiter zu verarbeiten und Änderungen zu verfolgen, die Sie später mit dem Server synchronisieren können, wenn Sie online sind.

Obwohl die Verwendung von Backbone.js mit einem Back-End, das REST-konform und damit kompatibel ist, einfacher zu verwenden ist, bedeutet dies nicht, dass Backbone.js nur damit arbeiten kann. Mit einigen Änderungen am standardmäßigen Synchronisierungsmechanismus von Backbone.js können Sie ihn an eine Vielzahl von Back-End-Dienst-APIs und Codierungsformaten anpassen.

Es ist erwähnenswert, dass andere Teile von Backbone.js ebenfalls flexibel und in gewisser Weise optional sind. Beispielsweise müssen Sie nicht die Standard-Template-Engine verwenden, die mit Underscore.js geliefert wird. Sie müssen nicht einmal die Ansichtskomponente von Backbone.js verwenden und können sie bei Bedarf durch etwas ganz anderes ersetzen.

Fehler Nr. 7: Speichern von Daten in Ansichten statt in Modellen

Ein Fehler, den wir als Anfänger beim Erlernen von Backbone.js oft machen, ist das Speichern von Daten direkt in Ansichten als Attribute. Diese Daten können vorhanden sein, um einen Zustand oder eine Benutzerauswahl zu verfolgen. Dies ist etwas, das vermieden werden sollte.

 var AudioPlayerVisualizer = Backbone.View.extend({ events: { 'click .btn-color': function(event) { this.colorHex = $(event.target).data('color-hex') this.render() } }, // ... })

Sie können immer einige zusätzliche Modelle und Sammlungen ohne Endpunkte erstellen. Diese können Ihnen dabei helfen, Daten zu speichern, die nicht unbedingt im Back-End gespeichert werden müssen oder vorübergehender Natur sein können. Wenn Sie sie in Modellen speichern, haben Sie den Vorteil, dass Sie auf Änderungen hören können. Die relevante Ansicht oder sogar mehrere Ansichten können diese Modelle beobachten und sich bei Bedarf neu rendern.

Stellen Sie sich vor, Sie hätten tatsächlich Zustandsverfolgungsvariablen für Ansichten gespeichert und müssten jedes Mal, wenn Sie sie ändern, die Rendermethode aufrufen. Wenn Sie nur einen Aufruf dieser Rendermethode verpassen, könnte Ihre Anwendung in Bezug auf das, was der Benutzer auf dem Bildschirm sieht, in einem fehlerhaften Zustand zurückbleiben. Darüber hinaus müssen Sie bei kleinen Ansichten diese Zustandsvariablen möglicherweise auf mehreren Ansichtsobjekten synchronisieren und dann auch die Render-Methode für sie aufrufen.

Fehler Nr. 8: Verwendung von jQuery „.on()“ anstelle von delegierten Ereignissen

Backbone.js hat meiner Meinung nach eine großartige Möglichkeit, mit DOM-Ereignissen umzugehen. Es nicht zu verwenden, bringt eine Reihe von Nachteilen mit sich. Die Ereignisbindungsfunktion „.on()“ von jQuery kann sich praktisch anfühlen, erweist sich aber auf lange Sicht oft als lästig. Wenn beispielsweise Elemente aus dem DOM gelöst werden, löscht jQuery automatisch alle Event-Handler, die mit „.on()“ an die Elemente gebunden sind. Dies bedeutet, dass jedes DOM-Ereignis, an das Sie versuchen, innerhalb einer Ansicht zu binden, erneut gebunden werden muss, wenn Sie das Stammelement vom DOM trennen und erneut anfügen.

 var AudioPlayerControls = Backbone.View.extend({ events: { 'click .btn-play, .btn-pause': function() { /* ... */ }, 'click .btn-prev': function() { /* ... */ }, 'click .btn-next': function() { /* ... */ }, 'click .btn-shuffle': function() { /* ... */ }, 'click .btn-repeat': function() { /* ... */ } }, // ... })

Wenn das Element, das dieser Ansicht entspricht, wieder an das DOM angehängt wird, müssen Sie lediglich „delegateEvents()“ für die Ansicht aufrufen, um alle diese Ereignisse zu binden.

Beachten Sie, dass es wichtig ist zu verstehen, wie diese Ereignisse gebunden sind. Anstatt das Ereignis an die vom Selektor angegebenen Elemente zu binden, bindet Backbone.js den Ereignishandler tatsächlich an das Stammelement der Ansicht. Dies funktioniert in fast allen Fällen gut und funktioniert für die meisten unserer Bedürfnisse sogar besser. Das Ändern oder Ersetzen der untergeordneten Elemente in der DOM-Unterstruktur der Ansicht erfordert nicht, dass Backbone.js jedes Ereignis erneut an die neuen Elemente bindet. Die vorhandenen Zuhörer arbeiten einfach weiter.

Dies verhindert jedoch, dass bestimmte Ereignisse mitgehört werden. Ein Beispiel ist, wo Sie auf Scroll-Ereignisse auf „Fenster“ oder auf einem untergeordneten scrollbaren Element lauschen möchten. Bei untergeordneten Elementen können Sie eine Unteransicht für dieses Element erstellen und die Ereignisse dort behandeln.

Fazit

Backbone.js ist als sehr kompaktes und dennoch erweiterbares Framework eine ausgezeichnete Wahl für Webanwendungen, die ein hohes Maß an Flexibilität hinter den Kulissen erfordern. Im Gegensatz zu Frameworks wie Angular.js und Ember.js, die Ihnen immer sagen, wie Sie das tun sollen, was Sie tun möchten, tritt Backbone.js einen Schritt zurück, gibt Ihnen einen leistungsstarken Satz von Tools an die Hand und lässt Sie entscheiden, wie Sie es verwenden Ihnen. Ich hoffe, dass dieses Backbone.js-Tutorial für Anfänger Ihnen hilft, einige der häufigsten Entwicklungsfehler zu vermeiden und etwas Erstaunliches damit zu bauen.