AngularJS Collaboration Board mit Socket.io

  • Erforderliche Kenntnisse: Mittlere JavaScript
  • Benötigt: Node.js, NPM
  • Projektzeit: 2 Stunden

AngularJS eignet sich besonders gut zum Erstellen umfangreicher clientseitiger Anwendungen im Browser. Wenn Sie dem Mix ein wenig Socket.io hinzufügen, werden die Dinge wirklich interessant. In diesem Artikel erstellen wir ein Echtzeit-Collaboration-Board, das AngularJS für die clientseitige Anwendung und Socket.io verwendet, um den Status zwischen allen verbundenen Clients zu teilen.

Lassen Sie uns ein wenig über die Haushaltsführung sprechen, bevor wir anfangen. Ich gehe davon aus, dass Sie ein grundlegendes Verständnis von HTML und JavaScript haben, da ich nicht jede kleine Ecke des Codes abdecken werde. Zum Beispiel werde ich die CSS- und JavaScript-Dateien, die ich im Kopf der HTML-Datei eingefügt habe, nicht aufrufen, da dort keine neuen Informationen vorhanden sind.

Ich ermutige Sie auch dazu Holen Sie sich den Code von meinem GitHub-Konto mitmachen. Mein guter Freund Brian Ford hat auch ein ausgezeichneter Socket.io Samen , auf die ich einige meiner ursprünglichen Ideen gestützt habe.

Die vier Hauptfunktionen, die wir im Collaboration Board wünschen, sind die Möglichkeit, eine Notiz zu erstellen. Lesen Sie die Notizen, aktualisieren Sie eine Notiz, löschen Sie eine Notiz und verschieben Sie zum Spaß eine Notiz an die Tafel. Ja, das stimmt, wir konzentrieren uns auf Standard-CRUD-Funktionen. Ich glaube, dass wir durch die Fokussierung auf diese grundlegenden Funktionen genügend Code abgedeckt haben, damit Muster entstehen können, damit Sie sie übernehmen und an anderer Stelle anwenden können.

wie man eigene Leinwände macht

01. Der Server

Wir werden zuerst mit dem Node.js-Server beginnen, da er als Grundlage dient, auf der wir alles andere aufbauen werden.

Wir werden mit Express und Socket.io einen Node.js-Server erstellen. Der Grund, warum wir Express verwenden, ist, dass es einen nützlichen Mechanismus zum Einrichten eines statischen Asset-Servers in Node.js bietet. Express bietet eine Reihe wirklich beeindruckender Funktionen, aber in diesem Fall werden wir es verwenden, um die Anwendung sauber zwischen Server und Client zu halbieren.

(Ich gehe davon aus, dass Node.js und NPM installiert sind. Eine schnelle Google-Suche zeigt Ihnen, wie Sie diese installieren können, wenn Sie dies nicht tun.)

02. Die nackten Knochen

Um die nackten Knochen des Servers aufzubauen, müssen wir einige Dinge tun, um den Betrieb aufzunehmen.



// app.js.

// A.1
var express = require ('express'),
app = express ();
server = require ('http'). createServer (app),
io = require ('socket.io'). listen (server);

// A.2
app.configure (function () {
app.use (express.static (__ dirname + '/ public'));
});

// A.3
server.listen (1337);

A.1 Wir deklarieren und instanziieren unsere Node.js-Module, damit wir sie in unserer Anwendung verwenden können. Wir deklarieren Express, instanziieren Express und erstellen dann einen HTTP-Server und senden die Express-Instanz hinein. Und von dort aus instanziieren wir Socket.io und fordern es auf, unsere Serverinstanz im Auge zu behalten.

A.2 Anschließend weisen wir unsere Express-App an, unser öffentliches Verzeichnis zum Bereitstellen von Dateien zu verwenden.

A.3 Wir starten den Server und weisen ihn an, den Port abzuhören 1337 .

Bisher war das ziemlich schmerzlos und schnell. Ich glaube, wir sind weniger als 10 Zeilen im Code und haben bereits einen funktionierenden Node.js-Server. Weiter!

03. Deklarieren Sie Ihre Abhängigkeiten

// packages.json
{
'name': 'angle-collab-board',
'description': 'AngularJS Collaboration Board',
'version': '0.0.1-1',
'privat': wahr,
'Abhängigkeiten': {
'express': '3.x',
'socket.io': '0.9.x'
}}
}}

Eine der schönsten Funktionen von NPM ist die Möglichkeit, Ihre Abhängigkeiten in a zu deklarieren packages.json Datei und installieren Sie sie dann automatisch über npm installieren in der Kommandozeile.

04. Verdrahten Sie Socket.io

Wir haben bereits die Kernfunktionen definiert, die wir in der Anwendung wünschen, und müssen daher Socket.io-Ereignis-Listener und einen geeigneten Abschluss einrichten, um das Ereignis für jede Operation zu behandeln.

Im folgenden Code werden Sie feststellen, dass es sich im Wesentlichen um eine Konfiguration von Ereignis-Listenern und Rückrufen handelt. Das erste Ereignis ist das Verbindung Ereignis, mit dem wir unsere anderen Ereignisse in der Schließung verkabeln.

io.sockets.on ('Verbindung', Funktion (Socket) {
socket.on ('createNote', Funktion (Daten) {
socket.broadcast.emit ('onNoteCreated', Daten);
});

socket.on ('updateNote', Funktion (Daten) {
socket.broadcast.emit ('onNoteUpdated', Daten);
});

socket.on ('deleteNote', Funktion (Daten) {
socket.broadcast.emit ('onNoteDeleted', Daten);
});

socket.on ('moveNote', Funktion (Daten) {
socket.broadcast.emit ('onNoteMoved', Daten);
});
});

Von hier aus fügen wir Hörer hinzu createNote , updateNote , deleteNote und moveNote . Und in der Rückruffunktion senden wir einfach, welches Ereignis passiert ist, damit jeder Client, der zuhört, benachrichtigt werden kann, dass das Ereignis aufgetreten ist.

Es gibt einige Dinge, die Sie über die Rückruffunktionen in den einzelnen Ereignishandlern beachten sollten. Erstens, wenn Sie ein Ereignis an alle anderen Personen als den Client senden möchten, der das von Ihnen eingefügte Ereignis ausgegeben hat Übertragung Vor dem emittieren Funktionsaufruf. Zweitens geben wir die Nutzlast der Veranstaltung einfach an die Interessenten weiter, damit sie sie nach eigenem Ermessen verarbeiten können.

05. Starten Sie Ihre Motoren!

Nachdem wir unsere Abhängigkeiten definiert und unsere Node.js-Anwendung mit Express- und Socket.io-Funktionen eingerichtet haben, ist es ganz einfach, den Node.js-Server zu initialisieren.

Zuerst installieren Sie Ihre Node.js-Abhängigkeiten wie folgt:

npm installieren

Und dann starten Sie den Server wie folgt:

Knoten app.js.

Und dann! Du gehst nach diese Adresse in Ihrem Browser. Bam!

06. Ein paar offene Gedanken, bevor Sie weitermachen

Ich bin in erster Linie ein Frontend-Entwickler und war anfangs ein wenig eingeschüchtert, einen Node.js-Server an meine Anwendung anzuschließen. Der AngularJS-Teil war ein Snap, aber serverseitiges JavaScript? Stellt die gruselige Musik aus einem Horrorfilm in die Warteschlange.

Ich war jedoch völlig enttäuscht, als ich herausfand, dass ich einen statischen Webserver in nur wenigen Codezeilen einrichten und in einigen weiteren Zeilen Socket.io verwenden konnte, um alle Ereignisse zwischen den Browsern zu verarbeiten. Und es war immer noch nur JavaScript! Aus Gründen der Aktualität behandeln wir nur einige Merkmale, aber ich hoffe, dass Sie am Ende des Artikels sehen werden, dass es leicht zu schwimmen ist - und das tiefe Ende des Pools nicht so beängstigend ist.

07. Der Kunde

Nachdem wir unser solides Fundament mit unserem Server aufgebaut haben, gehen wir zu meinem Lieblingsteil über - dem Client! Wir werden AngularJS, jQueryUI für den ziehbaren Teil und Twitter Bootstrap für eine Stilbasis verwenden.

08. Die nackten Knochen

Wenn ich eine neue AngularJS-Anwendung starte, möchte ich aus persönlichen Gründen schnell das absolute Minimum definieren, von dem ich weiß, dass ich anfangen muss, und dann so schnell wie möglich darüber iterieren.

Jede AngularJS-Anwendung muss mit mindestens einem vorhandenen Controller gebootet werden. Daher beginne ich im Allgemeinen immer hier.

Um die Anwendung automatisch zu booten, müssen Sie sie einfach hinzufügen ng-app an den HTML-Knoten, in dem die Anwendung leben soll. In den meisten Fällen ist das Hinzufügen zum HTML-Tag durchaus akzeptabel. Ich habe auch ein Attribut hinzugefügt ng-app um es zu sagen, dass ich die verwenden möchte App Modul, das ich gleich definieren werde.

// public / index.html

Ich weiß, dass ich mindestens einen Controller benötigen werde, und deshalb werde ich das mit aufrufen ng-controller und ihm eine Eigenschaft von zuweisen MainCtrl .

Jetzt sind wir also am Haken für ein Modul namens App und ein Controller namens MainCtrl . Lassen Sie uns fortfahren und sie jetzt erstellen.

Das Erstellen eines Moduls ist ziemlich einfach. Sie definieren es durch Aufrufen eckiges Modul und ihm einen Namen geben. Zum späteren Nachschlagen können Sie im zweiten Parameter eines leeren Arrays Untermodule zur Verwendung in der Anwendung einfügen. Es liegt außerhalb des Rahmens dieses Lernprogramms, ist jedoch praktisch, wenn Ihre Anwendung an Komplexität und Anforderungen zunimmt.

// public / js / collab.js
var app = angle.module ('app', []);

Wir werden ein paar leere Platzhalter in der deklarieren App Modul beginnend mit dem MainCtrl unten. Wir werden diese alle später ausfüllen, aber ich wollte die Grundstruktur von Anfang an veranschaulichen.

app.controller ('MainCtrl', Funktion ($ scope) {});

Wir werden auch die Socket.io-Funktionalität in a verpacken Steckdose Service, damit wir dieses Objekt kapseln können und es nicht im globalen Namespace herumschweben lassen.

app.factory ('Socket', Funktion ($ rootScope) {});

Und wenn wir schon dabei sind, werden wir eine Direktive namens deklarieren Haftnotiz dass wir verwenden werden, um die Sticky-Note-Funktionalität in zu kapseln.

app.directive ('stickyNote', Funktion (Socket) {});

Lassen Sie uns also überprüfen, was wir bisher getan haben. Wir haben die Anwendung mit gebootet ng-app und deklarierte unseren Anwendungscontroller im HTML. Wir haben auch das Anwendungsmodul definiert und das erstellt MainCtrl Controller, der Steckdose Service und die Haftnotiz Richtlinie.

09. Erstellen einer Haftnotiz

Nachdem wir das Grundgerüst der AngularJS-Anwendung eingerichtet haben, werden wir mit dem Aufbau der Erstellungsfunktion beginnen.

app.controller ('MainCtrl', Funktion ($ scope, socket) {// B.1
$ scope.notes = []; // B.2

// Eingehend
socket.on ('onNoteCreated', Funktion (Daten) {// B.3
$ scope.notes.push (Daten);
});

// Ausgehend
$ scope.createNote = function () {// B.4
var note = {
id: neues Datum (). getTime (),
Titel: 'Neue Notiz',
Körper: 'Ausstehend'
};

$ scope.notes.push (Anmerkung);
socket.emit ('createNote', Anmerkung);
};

B.1 AngularJS verfügt über eine integrierte Funktion zur Abhängigkeitsinjektion, sodass wir a injizieren $ scope Objekt und die Steckdose Bedienung. Das $ scope Das Objekt dient als ViewModel und ist im Grunde ein JavaScript-Objekt, in das einige Ereignisse eingebettet sind, um die bidirektionale Datenbindung zu ermöglichen.

B.2 Wir deklarieren das Array, an das die Ansicht gebunden werden soll.

B.3 Wir fügen einen Listener für das hinzu onNoteCreated Veranstaltung auf der Steckdose Service und Schieben der Ereignisnutzlast in die $ scope.notes Array.

B.4 Wir haben a erklärt createNote Methode, die einen Standard erstellt Hinweis Objekt und schiebt es in die $ scope.notes Array. Es verwendet auch die Steckdose Service, um die zu emittieren createNote Veranstaltung und bestehen die neue Notiz Objekt entlang.

Wie nennen wir es nun, da wir eine Methode zum Erstellen der Notiz haben? Das ist eine gute Frage! In der HTML-Datei fügen wir die integrierte AngularJS-Direktive hinzu klicken auf die Schaltfläche und fügen Sie dann die createNote Methodenaufruf als Attributwert.

Notiz erstellen

Zeit für einen kurzen Überblick über das, was wir bisher getan haben. Wir haben dem Array ein Array hinzugefügt $ scope Objekt in der MainCtrl Das wird alle Notizen für die Anwendung enthalten. Wir haben auch eine hinzugefügt createNote Methode auf der $ scope Objekt, um eine neue lokale Notiz zu erstellen und diese Notiz dann über das an die anderen Clients zu senden Steckdose Bedienung. Wir haben auch einen Ereignis-Listener hinzugefügt Steckdose Service, damit wir wissen, wann andere Kunden eine Notiz erstellt haben, damit wir sie unserer Sammlung hinzufügen können.

10. Anzeigen der Haftnotizen

Wir haben jetzt die Möglichkeit, ein Notizobjekt zu erstellen und es zwischen Browsern zu teilen, aber wie zeigen wir es tatsächlich an? Hier kommen Richtlinien ins Spiel.

Direktiven und ihre Feinheiten sind ein großes Thema, aber die Kurzversion bietet die Möglichkeit, Elemente und Attribute mit benutzerdefinierten Funktionen zu erweitern. Direktiven sind leicht mein Lieblingsteil von AngularJS, da Sie damit im Wesentlichen eine gesamte DSL (Domain Specific Language) um Ihre Anwendung in HTML erstellen können.

Es ist natürlich, dass wir, da wir Haftnotizen für unser Collaboration Board erstellen werden, eine erstellen sollten Haftnotiz Richtlinie. Direktiven werden definiert, indem die Direktivenmethode für ein Modul aufgerufen wird, für das Sie sie deklarieren möchten, und ein Name und eine Funktion übergeben werden, die ein Direktivendefinitionsobjekt zurückgeben. Das Direktivendefinitionsobjekt verfügt über viele mögliche Eigenschaften, die Sie definieren können. Wir werden hier jedoch nur einige für unsere Zwecke verwenden.

Ich empfehle, dass Sie die AngularJS-Dokumentation lesen, um die gesamten Listen der Eigenschaften anzuzeigen, die Sie für das Direktivendefinitionsobjekt definieren können.

app.directive ('stickyNote', Funktion (Socket) {
var linker = function (scope, element, attrs) {};

var controller = function ($ scope) {};

Rückkehr {
einschränken: 'A', // C.1
link: linker, // C.2
Controller: Controller, // C.3
Geltungsbereich: {// C.4
Anmerkung: '=',
ondelete: '&'
}}
};
});

Die Kunst der Kraft erwacht

C.1 Sie können Ihre Direktive auf einen bestimmten Typ von HTML-Element beschränken. Die beiden häufigsten sind Elemente oder Attribute, die Sie mit deklarieren IS und ZU beziehungsweise. Sie können es auch auf eine CSS-Klasse oder einen Kommentar beschränken, diese sind jedoch nicht so häufig.

C.2 In der Link-Funktion geben Sie Ihren gesamten DOM-Manipulationscode ein. Es gibt einige Ausnahmen, die ich gefunden habe, aber dies ist immer wahr (mindestens 99 Prozent der Zeit). Dies ist eine grundlegende Grundregel von AngularJS und deshalb habe ich sie betont.

C.3 Die Controller-Funktion funktioniert genauso wie der Hauptcontroller, den wir für die Anwendung definiert haben, aber der $ scope Das Objekt, das wir übergeben, ist spezifisch für das DOM-Element, auf dem die Direktive lebt.

C.4 AngularJS verfügt über ein Konzept des isolierten Geltungsbereichs, mit dem Sie explizit definieren können, wie der Geltungsbereich einer Richtlinie mit der Außenwelt kommuniziert. Wenn wir den Geltungsbereich nicht deklariert hätten, hätte die Direktive implizit vom übergeordneten Geltungsbereich mit einer Eltern-Kind-Beziehung geerbt. In vielen Fällen ist dies nicht optimal. Indem wir den Geltungsbereich isolieren, verringern wir die Wahrscheinlichkeit, dass die Außenwelt versehentlich und nachteilig den Status Ihrer Richtlinie beeinflusst.

Ich habe die bidirektionale Datenbindung für erklärt Hinweis mit dem = Symbol und ein Ausdruck, der an bindet Wavelet mit dem & Symbol. Bitte lesen Sie die AngularJS-Dokumentation, um eine vollständige Erläuterung des isolierten Umfangs zu erhalten, da dies eines der komplizierteren Themen im Framework ist.

Fügen wir dem DOM also tatsächlich eine Kurznotiz hinzu.

Wie jedes gute Framework bietet AngularJS sofort einige wirklich großartige Funktionen. Eine der handlichsten Funktionen ist ng-wiederholen . Mit dieser AngularJS-Direktive können Sie ein Array von Objekten übergeben und jedes Tag, auf dem es sich befindet, so oft duplizieren, wie sich Elemente im Array befinden. Im folgenden Fall iterieren wir über die Anmerkungen Array und Duplizieren der div Element und seine Kinder für die Länge der Anmerkungen Array.


×