ホームページ >ウェブフロントエンド >jsチュートリアル >Meteor と Node.js を使用してリアルタイム チャットを作成する例 application_node.js
Derby.js と比較してよく見かけるフレームワークは Meteor.js です。Derby と同様に、複数のクライアントでリアルタイムにビューを更新できます。ただし、上記とは少し方法が異なる場合があります。 Derby はさまざまなデータベースを簡単に使用できますが、実際には、Mongoose などのクライアントを介してデータベースにアクセスするための API は、MongoDB に近いものです。期待していたものに非常に近いです。
Meteor は現在、いくつかの欠点と論争のあるフレームワークですが、リアルタイム要件を備えたアプリケーションを構築する場合には非常に興味深い選択肢であると思われます。個人的には、従来のコールバックに基づくプログラミング形式の方が魅力的です。しかし、Derby では、その強力な裏に、堅牢なドキュメントと大規模な開発者コミュニティが欠けており、これは間違いなく大きな打撃です。おそらくこれは時間の経過とともに変わるでしょうが、Meteor は最近 1,100 万ドルを受け取ったため、依然として Meteor よりもはるかに遅いでしょう。この資金調達により、Meteor の存続と継続的なサポートが確保され、財政的にも開発的にも安定したフレームワークが得られます。新しい、現実的でありながらシンプルな Meteor アプリケーションの作成方法については、基本的に Tom's Vimeo スクリーンキャスト 初心者ガイドに基づいています。Tom's Vimeo スクリーンキャストとの最大の違いは、イベントをコピー&ペーストする方法ではないことです。 Meteor の例のコードを使用して、Enter キーを使用してメッセージを送信する独自の方法を段階的に説明します。
始めましょう。Meteor アプリケーションを作成する
Derby と Meteor に共通する大きな利点は、Node の組み込み npm ツールを使用する Derby とは異なり、Meteor は独自のコマンド ライン ツールを使用することです。
ターミナル (Mac OS X および Linux) で、次のコマンドを実行します (これを実行する前に、Node がインストールされていることを確認してください)
$curl https://install.meteor.com | /bin/sh
Metror はそれを自動的に実行し、コマンド ライン ツールをインストールします。
新しいプロジェクトを作成するには、まず作業ディレクトリに移動して以下のコードを実行します。これにより、Meteor と基本的なテンプレート プログラムを含むディレクトリが作成されます。
$meteor create chat
これで、そのディレクトリに移動し、以下のコードを実行して実行できます
$cdchat$meteor Running on: http://localhost:3000/
この最も基本的なアプリケーションを表示するには、最新のブラウザで http://localhost:3000/
を開くだけです。必要に応じて、Meteor の組み込み meteordeploy コマンドを使用してアプリケーションを Meteor 独自のサーバーにデプロイできます
$meteor deploy my-app-name.meteor.com
コードを更新して保存している限り、接続されているすべてのブラウザーがリアルタイムでページを更新します。
チャット アプリケーションの開発
Meteor Create コマンドによって生成されたフォルダーには、さまざまなファイルが表示されます。隠しファイルを表示する方法を知っている場合は、.meteor フォルダーも表示できます。このフォルダーには、Meteor 自体と MongoDB データ ファイルが含まれています。
アプリのルート フォルダーに、chat.html、chat.css、chat.js の 3 つのファイルがあるはずです。これら 3 つのファイルにはすべて独自の説明が付いています。 HTML ファイルには、chat.css によって定義されるアプリのモデルと外観が含まれています。 Javascript ファイルには、クライアント側とサーバー側で実行されるスクリプトが含まれています。アプリケーションのコードを見れば誰でも設定パラメータやパスワードを確認できるため、このスクリプト ファイルには何も入力しないことが重要です。
お気に入りのテキスト編集ソフトウェアで chat.js ファイルを開きます。個人的には、Sublime Text2 を使用するのが好きです。このツールはシンプルで、複数のマウス ステータス プロンプトがあるためです。
chat.js ファイルには次のコードがあります:
if (Meteor.is_client) { Template.hello.greeting = function () { return "Welcome to chat."; }; Template.hello.events = { 'click input' : function () { // template data, if any, is available in 'this' if (typeof console !== 'undefined') console.log("You pressed the button"); } }; } if (Meteor.is_server) { Meteor.startup(function () { // code to run on server at startup }); }
Meteor.js では、if 段落の Meteor.is_client と Meteor.is_server の 2 つの部分に注目してください。これらのブロック内のコードは個別に実行されます。このコードを実行するマシンがクライアントである場合、clint ブロック内のコードのみが実行されます。サーバーについても同様です。これは、実際のアプリケーションにおける Meteor のコード共有機能を示しています。
if の Meteor.is_client セクションと Meteor.is_server セクションのコードをすべて削除し、セクションを 1 つだけ残します:
if (Meteor.is_client) { }
スクリプト ファイルを保存すると、ブラウザがすぐに更新されて、この新しいコードが読み込まれることに注意してください。
ビューの作成
このスクリプト ファイルの作業を正式に開始する前に、チャット レコードを表示するための新しいビューを作成し、hello という名前のテンプレート タグを body タグに含める必要があります。次の部分
<head> <title>chat</title> </head> <body> </body>
次に、body タグに次の文を追加します
{{> entryfield}}
Meteor使用的模板系统与Mustache很相似.大括号{% raw %}{{}}{% endraw %}表示要呈现的内容. 通过简单地在两对大括号里添加内容如{% raw %}{{hello}}{% endraw %}, 模板系统会用hello这个变量的值来替换它. 后面会更详细的介绍.
注意到了在entryfield这个词前面有个大于号>了吗? 使用该符号来指定渲染哪一个模板.
<template name="entryfield"> <input type="text" id="name" placeholder="Name" /> <input type="text" id="message" placeholder="Your Message" /> </template>
在这个例子中,template标签有单个属性, 即模板的名字, 这就是我们要渲染的模板, 注意, 模板的名字要和body里的代码指定的模板名字一样 ({{> entryfield}})
查看浏览器, 你会发现页面已经刷新了, 输入框已经呈现出来了.
接下来, 在body里边添加另外的一个mutache标签用以渲染讯息列表
{{> messages}}
最后, 我们还需要新建一个名叫messages的模板. 在entryfield模板下面添加下面这段代码
<template name="messages"> <p> {{#each messages}} <strong>{{name}}</strong>- {{message}} {{/each}} </p> </template>
注意到each子句. 在Meteor中你可以使用如下的语法来遍历一个数组模板
{{#each [name of array]}} {{/each}}
使用each循环时,上下文会有所改变. 当引用变量的时候, 实际上你引用的是每一个数组元素的值.
例如,在我们的chat应用中, 我们遍历了数组模板"messages"里边的每个元素, 该数组可以像下面这样,
[ { "name": "Andrew", "message": "Hello world!" }, { "name": "Bob", "message": "Hey, Andrew!"" } ]
然后, 在each循环中, 你可以看到{% raw %}{{message}}{% endraw %}{% raw %}{{name}}{% endraw %}, 这会引用 每一个数组元素的值来替代(Andrew 和 Bob 替换 name, 以及各自的问候信息.)
当返回到你的浏览器, 你还看不到任何的改变. 因为讯息数组还没被传送到模板, 所以Meteor遍历不到任何东西来呈现.
你的chat.html最后应该是这样的
chat {{> entryfield}} {{> messages}} <template name="entryfield"> <input type="text" id="name" placeholder="Name" /> <input type="text" id="message" placeholder="Your Message" /> </template>{{#each messages}} {{name}}- {{message}}
{{/each}}
Javascript
从现在开始, 我们处理的大部分代码都是客户端代码, 所以, 除非特别说明, 以下的代码都是在if (Meteor.is_client)代码块中.
在我们编写展示讯息的代码之前,让我们先新建一个Collection. 从本质上讲, 这是一组Models. 换句话说, 在这个chat应用的环境下, Messages collection保存着整个聊天记录, 而每条讯息记录是一个Model.
在if语句前, 添加如下代码来初始化Collection:
Messages = new Meteor.Collection('messages');
因为我们希望这个Collection可以在客户端和服务端被创建, 所以我们把它写在了客户端代码块之外.
由于Meteor为我们做了大部分的工作, 要展示聊天记录是非常容易的. 只需要把下面的代码添加进if语句里边.
Template.messages.messages = function(){ return Messages.find({}, { sort: { time: -1 }}); }
让我们拆开来分析这段代码:
Template.messages.messages = function(){ … }
第一部分Template表示我们正在修改一个模板的行为.
Template.messages.messages = function(){ … }
第二部分messages是模板的名字, 表示是在修改哪一个模板. 例如,如果我们想要对"entryfield"模板做些什么, 只需把代码改成
Template.entryfields.variable = function(){ … }
(在这里, 请别这么做)
Template.messages.messages = function(){ … }
第三部分的这个messages代表的是一个这个模板里的一个变量. 还记得我们的each循环遍历messages吗? 这就是那个mesaages.
当你打开浏览器时, 页面还是没有什么改变. 这是意料之中的事, 因为我们只抓取的讯息, 而没有展示出来.
此时,你的chat.js应该是这样的. 是否很惊讶就只需在服务器写这么些代码我们就能展示一个实时的聊天记录应用.
Messages = new Meteor.Collection('messages'); if (Meteor.is_client) { Template.messages.messages = function(){ return Messages.find({}, { sort: { time: -1 }}); } }
在console里添加Message
这部分的内容是可选的, 当然它有助于你调试程序. 你可以直接跳过往下学习建立form来响应键盘事件(key press).
如果你想要测试你的讯息显示代码, 你可以手动插入一条记录到数据库. 打开你的浏览器控制台, 并输入如下:
Messages.insert({ name: 'Andrew', message: 'Hello world!', time: 0 })
这将会在数据库中新建一条记录, 如果正确的操作了的话,那浏览器就会即刻更新这条讯息在页面上.
消息表单
回到chat.js文件当中,我们会将供输入的form和数据库链接起来以接收用户聊天数据的提交。在底部添加下面的代码,不过注意要在if语句块中。
Template.entryfield.events = { "keydown #message": function(event){ if(event.which == 13){ // Submit the form var name = document.getElementById('name'); var message = document.getElementById('message'); if(name.value != '' && message.value != ''){ Messages.insert({ name: name.value, message: message.value, time: Date.now() }); name.value = ''; message.value = ''; } } } }
代码有点多,让我们再回顾一遍。你也许还记得,在Template后面的第二个单词决定了我们正在修改的是哪个模板。不过跟之前不同的是,我们写的代码是用来绑定数据库和messages模板的,我们正在修改的模板是entryfield。
这个模板中events的属性包含了一个object,events的属性按照下面的格式呈现:
"[eventname] [selector]"
例如,如果我们想为一个ID为hello的button绑定一个点击事件的话,我们会把下面的代码加入到events的个结构体当中。
"click #hello": function(event){ … }
在我们的例子当中,我们是将一个函数绑定到了ID为“message”的一个keydown事件当中。如果你还记得,这段代码早在我们在chat.html文件中建立模板的时候就已经设定好了。
在事件对象中,每个key都有一个函数作为它的值。这个函数在事件被调用时执行,其中事件对象作为第一个参数传递给该函数。在我们的app里,每当ID带有“message”的输入栏中有任意键被按下(keydown)时,该函数就被调用了。
函数内的代码相当简单。首先,我们检查回车键是否被按下(输入中有13的关键代码)。第二,我们通过ID取得两个输入栏的DOM元素。第三,我们检查并确保输入值不为空,以防止用户提交一个空的名字或信息(name or message)。
注意下面的代码很重要。这段代码是将message插入数据库。
Messages.insert({ name: name.value, message: message.value, time: Date.now() });
正如你看到的,这和我们插入到控制台的代码类似,但不是硬编码的数值,我们用的是DOM元素的值。此外,我们加入了当前时间,以保证聊天日志被正确的按时间排序。
最后,我们将两个输入的值简单的设为''以清空输入栏。
现在,如果你进入浏览器,你可以试着输入一个名字与信息到两个输入栏。按下回车以后,输入栏将被清除,一个新的消息会出现在你的输入字段的正下方。打开另一个浏览器窗口,导航到同一个URL(http://localhost:3000/)。试着键入另一个信息,而
正如你看到的,Meteor非常强大。不需要写一行明确更新消息日志的代码,新的信息显示出来并同步到多个浏览器和客户端。
总结
虽然Meteor工作起来非常酷,而且也有一些非常有用的应用支持它,比如Derby.js,但它是不成熟的。一个说明这一点例子就是,浏览文档并找找红色的引文。例如,关于MongoDB集合该文档做了如下陈述:
目前客户端被给予集合的完全写访问权限。它们可以执行任意的更新命令。一旦我们建立鉴权认证,你将能够限制客户端的直接插入,更新和删除。我们也在考虑校验器或者其他类似ORM的功能。
任何用户拥有完全的写访问权限是一个非常大的问题,因为对任何一个app产品——如果一个用户对你的整个数据库有写访问权限,这是一个相当大的安全问题。
看到Meteor(和Derby.js!)在像哪个方向前进是令人激动的,但是除非它成熟一点,它可能不是一个产品级应用的最好选择。期待那1100万美元资金能很好的利用起来。