コンテンツ
- 01.サーバー
- 02.裸の骨
- 03.依存関係を宣言します
- 04.Socket.ioを配線します
- 05.エンジンを始動してください!
- 06.先に進む前にいくつかの率直な考え
- 07.クライアント
- 08.裸の骨
- 09.付箋を作成する
- 10.付箋を表示する
- 11.付箋を削除する
- 12.付箋を更新する
- 13.付箋を移動する
- 14.ボーナス
- 15.結論
- これが好きですか?これらを読んでください!
- 必要な知識: 中級JavaScript
- 必要なもの: Node.js、NPM
- プロジェクト時間: 2時間
AngularJSは、ブラウザーでリッチなクライアント側アプリケーションを作成するのに特に適しています。小さなSocket.ioをミックスに追加すると、非常に興味深いものになります。この記事では、クライアント側アプリケーションにAngularJSを使用し、接続されているすべてのクライアント間で状態を共有するSocket.ioを使用するリアルタイムコラボレーションボードを構築します。
始める前に、ハウスキーピングについて少し説明しましょう。コードの隅々までカバーするつもりはないので、HTMLとJavaScriptについて基本的に理解していると思います。たとえば、HTMLファイルの先頭に含めたCSSファイルとJavaScriptファイルは、新しい情報がないため、呼び出すつもりはありません。
また、GitHubアカウントからコードを取得してフォローすることをお勧めします。私の親友であるBrianFordも、優れたSocket.ioシードを持っています。これは、私が独自のアイデアのいくつかに基づいています。
コラボレーションボードに必要な4つの主な機能は、メモの作成、メモの読み取り、メモの更新、メモの削除、そして楽しみのためにボード上でメモを移動する機能です。はい、その通りです。私たちは標準のCRUD機能に重点を置いています。これらの基本的な機能に焦点を当てることで、パターンが出現するのに十分なコードをカバーし、パターンを他の場所に適用できるようになると思います。
01.サーバー
Node.jsサーバーは、他のすべてを構築するための基盤として機能するため、最初にNode.jsサーバーから始めます。
ExpressとSocket.ioを使用してNode.jsサーバーを構築します。 Expressを使用する理由は、Node.js内に静的アセットサーバーをセットアップするための優れたメカニズムを提供するためです。 Expressには非常に優れた機能が多数付属していますが、この場合は、Expressを使用して、サーバーとクライアントの間でアプリケーションをクリーンに二分します。
(私は、Node.jsとNPMがインストールされていることを前提に運用しています。Googleですばやく検索すると、インストールされていない場合にこれらをインストールする方法がわかります。)
02.裸の骨
したがって、サーバーの骨組みを構築するには、起動して実行するためにいくつかのことを行う必要があります。
// 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アプリケーションで使用できるように、Node.jsモジュールを宣言してインスタンス化しています。 Expressを宣言し、Expressをインスタンス化してから、HTTPサーバーを作成し、Expressインスタンスをそのサーバーに送信します。そしてそこから、Socket.ioをインスタンス化し、サーバーインスタンスを監視するように指示します。
A.2次に、Expressアプリに、パブリックディレクトリを使用してファイルを提供するように指示します。
A.3サーバーを起動し、ポートでリッスンするように指示します 1337.
これまでのところ、それはかなり痛みがなく、迅速でした。コードは10行未満で、すでに機能するNode.jsサーバーがあります。以降!
03.依存関係を宣言します
// packages.json
{
"名前": "angular-collab-board"、
「説明」:「AngularJSコラボレーションボード」、
"バージョン": "0.0.1-1"、
「プライベート」:true、
「依存関係」:{
「エクスプレス」:「3.x」、
"socket.io": "0.9.x"
}
}
NPMの最も優れた機能の1つは、依存関係を宣言する機能です。 packages.json ファイルを作成し、を介して自動的にインストールします npmインストール コマンドラインで。
04.Socket.ioを配線します
アプリケーションに必要なコア機能はすでに定義されているため、Socket.ioイベントリスナーと、各操作のイベントを処理するための適切なクロージャーを設定する必要があります。
以下のコードでは、基本的にイベントリスナーとコールバックの構成であることがわかります。最初のイベントは 接続 イベント。これは、クロージャー内の他のイベントを接続するために使用します。
io.sockets.on( ’connection’、function(socket){
socket.on( ’createNote’、function(data){
socket.broadcast.emit( ’onNoteCreated’、data);
});
socket.on( ’updateNote’、function(data){
socket.broadcast.emit( ’onNoteUpdated’、data);
});
socket.on( ’deleteNote’、function(data){
socket.broadcast.emit( ’onNoteDeleted’、data);
});
socket.on( ’moveNote’、function(data){
socket.broadcast.emit( ’onNoteMoved’、data);
});
});
ここからリスナーを追加します createNote, updateNote, deleteNote そして moveNote。また、コールバック関数では、発生したイベントをブロードキャストするだけなので、リッスンしているクライアントにイベントが発生したことを通知できます。
個々のイベントハンドラーのコールバック関数について指摘する価値のあることがいくつかあります。 1つは、挿入したイベントを発行したクライアント以外のすべての人にイベントを送信する場合です。 放送 の前に 放出する 関数呼び出し。次に、イベントのペイロードを関係者に渡すだけで、関係者は適切と思われる方法でイベントを処理できます。
05.エンジンを始動してください!
依存関係を定義し、ExpressとSocket.ioの機能を使用してNode.jsアプリケーションをセットアップしたので、Node.jsサーバーを初期化するのは非常に簡単です。
まず、次のようにNode.jsの依存関係をインストールします。
npmインストール
次に、次のようにサーバーを起動します。
ノードapp.js
その後!ブラウザでこのアドレスにアクセスします。バム!
06.先に進む前にいくつかの率直な考え
私は主にフロントエンド開発者であり、最初はNode.jsサーバーをアプリケーションに接続することに少し不安を感じていました。 AngularJSの部分は簡単でしたが、サーバー側のJavaScriptですか?ホラー映画から不気味な音楽をキューに入れます。
しかし、ほんの数行のコードで静的Webサーバーをセットアップでき、さらに数行でSocket.ioを使用してブラウザー間のすべてのイベントを処理できることに気づきました。そしてそれはまだJavaScriptだけでした!適時性のために、いくつかの機能のみを取り上げていますが、記事の終わりまでに、泳ぎやすく、プールの奥がそれほど怖くないことがわかることを願っています。
07.クライアント
サーバーとの強固な基盤が整ったので、私のお気に入りの部分であるクライアントに移りましょう。ドラッグ可能な部分にはAngularJS、jQueryUIを使用し、スタイルベースにはTwitterBootstrapを使用します。
08.裸の骨
個人的な好みの問題として、新しいAngularJSアプリケーションを起動するときは、開始する必要があることがわかっている最低限のことをすばやく定義して、できるだけ早くそれを繰り返し始めるのが好きです。
すべてのAngularJSアプリケーションは、少なくとも1つのコントローラーが存在する状態でブートストラップする必要があるため、通常、ここから始めます。
アプリケーションを自動的にブートストラップするには、単に追加する必要があります ng-app アプリケーションを配置するHTMLノードに移動します。ほとんどの場合、HTMLタグに追加することは完全に受け入れられます。また、属性を追加しました ng-app 使用したいことを伝えるために アプリ モジュール。これについてはすぐに定義します。
// public / index.html
html ng-app = "app">
少なくとも1つのコントローラーが必要になることはわかっているので、 ng-コントローラー のプロパティを割り当てます MainCtrl.
body ng-controller = "MainCtrl"> / body>
だから今、私たちはという名前のモジュールのフックにいます アプリ とという名前のコントローラー MainCtrl。さあ、今すぐ作成しましょう。
モジュールの作成はかなり簡単です。あなたはそれを呼び出すことによってそれを定義します angle.module それに名前を付けます。後で参照できるように、空の配列の2番目のパラメーターは、アプリケーションで使用するサブモジュールを挿入できる場所です。これはこのチュートリアルの範囲外ですが、アプリケーションの複雑さとニーズが増大し始めたときに便利です。
// public / js / collab.js
var app = angle.module( ’app’、[]);
でいくつかの空のプレースホルダーを宣言します アプリ で始まるモジュール MainCtrl 未満。これらは後ですべて記入しますが、最初から基本的な構造を説明したいと思いました。
app.controller( ’MainCtrl’、function($ scope){});
また、Socket.io機能を ソケット そのオブジェクトをカプセル化し、グローバル名前空間に浮かせたままにしないようにするためのサービス。
app.factory( ’socket’、function($ rootScope){});
そして、私たちがそれに取り組んでいる間に、次のようなディレクティブを宣言します 付箋 に付箋機能をカプセル化するために使用します。
app.directive( ’stickyNote’、function(socket){});
それでは、これまでに行ったことを確認しましょう。を使用してアプリケーションをブートストラップしました ng-app そして、HTMLでアプリケーションコントローラーを宣言しました。また、アプリケーションモジュールを定義し、 MainCtrl コントローラー、 ソケット サービスと 付箋 指令。
09.付箋を作成する
AngularJSアプリケーションのスケルトンが配置されたので、作成機能の構築を開始します。
app.controller( ’MainCtrl’、function($ scope、socket){// B.1
$ scope.notes = []; // B.2
//着信
socket.on( ’onNoteCreated’、function(data){// B.3
$ scope.notes.push(data);
});
//発信
$ scope.createNote = function(){// B.4
var note = {
id:new Date()。getTime()、
タイトル:「新しいメモ」、
本文:「保留中」
};
$ scope.notes.push(note);
socket.emit( ’createNote’、note);
};
B.1 AngularJSには依存性注入機能が組み込まれているため、 $ scope オブジェクトと ソケット サービス。ザ・ $ scope オブジェクトはViewModelとして機能し、基本的にはJavaScriptオブジェクトであり、双方向のデータバインディングを可能にするためにいくつかのイベントが組み込まれています。
B.2ビューをバインドするために使用する配列を宣言しています。
B.3リスナーを追加します onNoteCreated のイベント ソケット サービスとイベントペイロードのプッシュ $ scope.notes アレイ。
B.4宣言しました createNote デフォルトを作成するメソッド 注意 オブジェクトとそれをにプッシュします $ scope.notes アレイ。それはまた使用します ソケット 放出するサービス createNote イベントを通過し、 新しいメモ に沿ってオブジェクト。
メモを作成するメソッドができたので、どのように呼び出しますか?それは良い質問です! HTMLファイルに、組み込みのAngularJSディレクティブを追加します ng-クリック ボタンに追加し、 createNote 属性値としてのメソッド呼び出し。
button id = "createButton" ng-click = "createNote()">メモ/ボタンの作成>
これまでに行ったことを簡単に確認する時間です。に配列を追加しました $ scope 内のオブジェクト MainCtrl これで、アプリケーションのすべてのメモが保持されます。また、 createNote 上の方法 $ scope 新しいローカルノートを作成し、そのノートを他のクライアントにブロードキャストするオブジェクト ソケット サービス。また、にイベントリスナーを追加しました ソケット 他のクライアントがいつメモを作成したかを知ることができるので、コレクションに追加できます。
10.付箋を表示する
これで、メモオブジェクトを作成してブラウザ間で共有できるようになりましたが、実際にどのように表示するのでしょうか。これがディレクティブの出番です。
ディレクティブとその複雑さは広大なテーマですが、短いバージョンでは、カスタム機能を使用して要素と属性を拡張する方法を提供します。ディレクティブは、アプリケーションの周囲にDSL(ドメイン固有言語)全体をHTMLで本質的に作成できるため、AngularJSについての私のお気に入りの部分です。
コラボレーションボード用の付箋を作成するので、作成する必要があるのは当然です。 付箋 指令。ディレクティブは、宣言するモジュールでディレクティブメソッドを呼び出し、ディレクティブ定義オブジェクトを返す名前と関数を渡すことによって定義されます。ディレクティブ定義オブジェクトには、定義できる多くの可能なプロパティがありますが、ここでは、目的のためにいくつかを使用します。
AngularJSのドキュメントをチェックして、ディレクティブ定義オブジェクトで定義できるプロパティのリスト全体を確認することをお勧めします。
app.directive( ’stickyNote’、function(socket){
varリンカー= function(scope、element、attrs){};
var controller = function($ scope){};
戻り値{
制限:「A」、// C.1
リンク:リンカー、// C.2
コントローラー:コントローラー、// C.3
スコープ:{// C.4
注: ’=’、
ondelete: ’&’
}
};
});
C.1ディレクティブを特定のタイプのHTML要素に制限できます。最も一般的な2つは、を使用して宣言する要素または属性です。 E そして A それぞれ。 CSSクラスまたはコメントに制限することもできますが、これらはそれほど一般的ではありません。
C.2リンク機能は、すべてのDOM操作コードを配置する場所です。私が見つけたいくつかの例外がありますが、これは常に当てはまります(少なくとも99%の確率で)。これがAngularJSの基本的な基本ルールであり、私がそれを強調した理由です。
C.3コントローラー機能は、アプリケーション用に定義したメインコントローラーと同じように機能しますが、 $ scope 渡すオブジェクトは、ディレクティブが存在するDOM要素に固有です。
C.4 AngularJSには分離スコープの概念があり、ディレクティブのスコープが外部と通信する方法を明示的に定義できます。スコープを宣言しなかった場合、ディレクティブは親子関係で親スコープから暗黙的に継承されます。多くの場合、これは最適ではありません。スコープを分離することにより、外の世界が不注意に、そしてあなたの指令の状態に悪影響を与える可能性を軽減します。
に双方向のデータバインディングを宣言しました 注意 とともに = にバインドする記号と式 ondelete とともに & シンボル。分離スコープはフレームワークでより複雑な主題の1つであるため、分離スコープの完全な説明については、AngularJSのドキュメントをお読みください。
それでは、実際にDOMに付箋を追加しましょう。
他の優れたフレームワークと同様に、AngularJSにはすぐに使用できる非常に優れた機能がいくつか付属しています。最も便利な機能の1つは ng-repeat。このAngularJSディレクティブを使用すると、オブジェクトの配列を渡すことができ、配列内のアイテムの数だけ、タグが付いているものを複製します。以下のケースでは、繰り返し処理を行っています。 ノート 配列と複製 div 要素とその子の長さ ノート アレイ。
div sticky-note ng-repeat = "note in notes" note = "note" ondelete = "deleteNote(id)">
button type = "button" ng-click = "deleteNote(note.id)">×/ button>
input ng-model = "note.title" ng-change = "updateNote(note)" type = "text">
textarea ng-model = "note.body" ng-change = "updateNote(note)"
> {{note.body}} / textarea>
/ div>
の美しさ ng-repeat 渡した配列にバインドされ、配列にアイテムを追加すると、DOM要素が自動的に更新されます。これをさらに一歩進めて、標準のDOM要素だけでなく他のカスタムディレクティブも繰り返すことができます。それがあなたが見る理由です 付箋 要素の属性として。
明確にする必要があるカスタムコードの他の2つのビットがあります。スコープを分離しました ポストイット 2つのプロパティのディレクティブ。 1つ目は、バインディングで定義された分離スコープです。 注意 プロパティ。これは、親スコープでメモオブジェクトが変更されるたびに、ディレクティブ内の対応するメモオブジェクトが自動的に更新されることを意味します。その逆も同様です。他の定義された分離スコープは ondelete 属性。これが意味するのは ondelete ディレクティブで呼び出されると、にある式はすべて呼び出されます。 ondelete ディレクティブをインスタンス化するDOM要素の属性。
ディレクティブがインスタンス化されると、それがDOMに追加され、リンク関数が呼び出されます。これは、要素にいくつかのデフォルトのDOMプロパティを設定する絶好の機会です。渡す要素パラメーターは実際にはjQueryオブジェクトであるため、jQuery操作を実行できます。
(AngularJSには実際にはjQueryのサブセットが組み込まれていますが、jQueryのフルバージョンが既に含まれている場合、AngularJSはそれに従います。)
app.directive( ’stickyNote’、function(socket){
varリンカー= function(scope、element、attrs){
//それを良くするためのいくつかのDOM開始
element.css( 'left'、 '10px');
element.css( 'top'、 '50px');
element.hide()。fadeIn();
};
});
上記のコードでは、付箋をステージに配置してフェードインするだけです。
11.付箋を削除する
付箋を追加して表示できるようになったので、次は付箋を削除します。付箋の作成と削除は、メモがバインドされている配列からアイテムを追加および削除することです。これは、その配列を維持する親スコープの責任です。そのため、ディレクティブ内から削除要求を開始しますが、親スコープに実際の手間のかかる作業を任せます。
これが、ディレクティブで式で定義された分離スコープを作成するというすべての問題を経験した理由です。そのため、ディレクティブはdeleteイベントを内部で受け取り、処理のために親に渡すことができます。
ディレクティブ内のHTMLに注意してください。
button type = "button" ng-click = "deleteNote(note.id)">×/ button>
私が次に言うことは、遠い道のりのように思えるかもしれませんが、私たちが同じ側にいることを忘れないでください。付箋紙の右上隅にあるボタンをクリックすると、 deleteNote ディレクティブのコントローラーで、 note.id 値。次に、コントローラーは呼び出します ondelete、 次に、それに接続した式を実行します。ここまでは順調ですね?コントローラでローカルメソッドを呼び出しています。このメソッドは、分離されたスコープで定義されている式を呼び出すことで、それを渡します。親で呼び出される式は、たまたま呼び出されます deleteNote 同じように。
app.directive( ’stickyNote’、function(socket){
var controller = function($ scope){
$ scope.deleteNote = function(id){
$ scope.ondelete({
やった
});
};
};
戻り値{
制限:「A」、
リンク:リンカー、
コントローラー:コントローラー、
スコープ:{
注: ’=’、
ondelete: ’&’
}
};
});
(式で定義された分離スコープを使用する場合、パラメーターはオブジェクトマップで送信されます。)
親スコープでは、 deleteNote 呼び出され、を使用してかなり標準的な削除を行います angle.forEach notes配列を反復処理するユーティリティ関数。関数がローカルビジネスを処理すると、関数は先に進み、それに応じて世界の他の地域にイベントを発行します。
app.controller( ’MainCtrl’、function($ scope、socket){
$ scope.notes = [];
//着信
socket.on( ’onNoteDeleted’、function(data){
$ scope.deleteNote(data.id);
});
//発信
$ scope.deleteNote = function(id){
var oldNotes = $ scope.notes、
newNotes = [];
angle.forEach(oldNotes、function(note){
if(note.id!== id)newNotes.push(note);
});
$ scope.notes = newNotes;
socket.emit( ’deleteNote’、{id:id});
};
});
12.付箋を更新する
私たちは素晴らしい進歩を遂げています!これまでに、私たちが行っているこの旋風ツアーからいくつかのパターンが出現し始めていることを願っています。リストの次の項目は更新機能です。
実際のDOM要素から始めて、サーバーまで追跡し、クライアントに戻ります。まず、付箋のタイトルまたは本文がいつ変更されるかを知る必要があります。 AngularJSはフォーム要素をデータモデルの一部として扱うため、双方向のデータバインディングを簡単に接続できます。これを行うには、 ng-model ディレクティブを作成し、バインドするプロパティを入力します。この場合、使用します note.title そして note.body それぞれ。
これらのプロパティのいずれかが変更された場合、その情報をキャプチャして渡す必要があります。私たちはこれを ng-change ディレクティブとそれを使用して呼び出す updateNote ノートオブジェクト自体を渡します。 AngularJSは、非常に巧妙なダーティチェックを実行して、何かの値が含まれているかどうかを検出します ng-model が変更されてから、次の式が実行されます。 ng-change.
input ng-model = "note.title" ng-change = "updateNote(note)" type = "text">
textarea ng-model = "note.body" ng-change = "updateNote(note)"> {{note.body}} / textarea>
使用の利点 ng-change ローカル変換はすでに行われており、メッセージの中継は私たちが担当しているということです。コントローラでは、 updateNote と呼ばれ、そこから放出します updateNote サーバーが他のクライアントにブロードキャストするためのイベント。
app.directive( ’stickyNote’、function(socket){
var controller = function($ scope){
$ scope.updateNote = function(note){
socket.emit( ’updateNote’、note);
};
};
});
そして、ディレクティブコントローラでは、 onNoteUpdated ローカルバージョンを更新できるように、別のクライアントからのメモがいつ更新されたかを知るイベント。
var controller = function($ scope){
//着信
socket.on( ’onNoteUpdated’、function(data){
//同じ音符の場合は更新します
if(data.id == $ scope.note.id){
$ scope.note.title = data.title;
$ scope.note.body = data.body;
}
});
};
13.付箋を移動する
この時点で、基本的にCRUDキディプールを一周しました。生活は良好です。パーラーのトリックで友達を感動させるために、画面上でメモを移動したり、座標をリアルタイムで更新したりする機能を追加します。慌てる必要はありません。あと数行のコードです。この大変な努力はすべて報われるでしょう。約束します!
特別ゲストのjQueryUIをパーティーに招待し、ドラッグ可能なもののためにすべてを行いました。メモをローカルにドラッグする機能を追加すると、1行のコードしか必要ありません。追加する場合 element.draggable(); リンカー機能に、メモをドラッグできるようになったため、Survivorによる「EyeoftheTiger」が聞こえ始めます。
ドラッグがいつ停止したかを知り、渡す新しい座標をキャプチャしたいと思います。 jQueryUIは非常に賢い人々によって構築されたため、ドラッグが停止したときに、stopイベントのコールバック関数を定義するだけで済みます。私たちはつかみます note.id スコープオブジェクトと、からの左側と上部のCSS値 ui オブジェクト。その知識を使って、私たちはずっとやってきたことをします:放出します!
app.directive( ’stickyNote’、function(socket){
varリンカー= function(scope、element、attrs){
element.draggable({
停止:function(event、ui){
socket.emit( ’moveNote’、{
id:scope.note.id、
x:ui.position.left、
y:ui.position.top
});
}
});
socket.on( ’onNoteMoved’、function(data){
//同じ音符の場合は更新します
if(data.id == scope.note.id){
element.animate({
左:data.x、
上:data.y
});
}
});
};
});
この時点で、ソケットサービスからの移動関連のイベントもリッスンしているのは当然のことです。この場合、それは onNoteMoved イベントであり、メモが一致する場合は、左側と上部のCSSプロパティを更新します。バム!完了しました。
14.ボーナス
これはボーナスセクションであり、10分以内に達成できると絶対に確信していなかった場合は含めません。ライブサーバーにデプロイします(それがいかに簡単であるかに今でも驚いています)。
まず、無料のNodejitsuトライアルにサインアップする必要があります。トライアルは30日間無料で、足を濡らすのに最適です。
アカウントを作成したら、jitsuパッケージをインストールする必要があります。これは、コマンドラインから次の方法で実行できます。 $ npm install jitsu -g.
次に、コマンドラインからを介してログインする必要があります $ jitsuログイン クレデンシャルを入力します。
アプリに直接アクセスしていることを確認し、次のように入力します $ jitsuデプロイ 質問をステップスルーします。私は通常、可能な限りデフォルトのままにします。つまり、アプリケーションに名前を付けますが、サブドメインなどは付けません。
そして、私の親愛なる友人、それはそれにあるすべてです!アプリケーションがデプロイされて準備が整うと、サーバーの出力からアプリケーションへのURLが取得されます。
15.結論
この記事では、AngularJSの多くの分野について説明しましたが、その過程で多くの楽しみがあったことを願っています。 AngularJSとSocket.ioを使用して約200行のコードで達成できることは本当に素晴らしいと思います。
要点に焦点を当てるために取り上げなかったことがいくつかありますが、ソースをプルダウンしてアプリケーションを試してみることをお勧めします。私たちは強力な基盤を構築しましたが、追加できる機能はまだたくさんあります。ハッキングをゲット!
Lukas Ruebbelkeはテクノロジー愛好家であり、AngularJS in Action for ManningPublicationsを共同執筆しています。彼の好きなことは、彼と同じように人々を新しいテクノロジーに興奮させることです。彼はPhoenixWeb Application User Groupを運営しており、犯罪の仲間と一緒に複数のハッカソンを主催してきました。
これが好きですか?これらを読んでください!
- アプリの作り方
- 私たちのお気に入りのウェブフォント-そしてそれらは一銭もかかりません
- 拡張現実の次のステップを発見する
- 無料のテクスチャをダウンロード:高解像度で今すぐ使用可能