什么是 Meteor?Meteor 是一種新的 JavaScript 框架,用于自動化和簡化實(shí)時(shí)運(yùn)行的 Web 應(yīng)用程序的開發(fā)。它使用一個(gè)名為分布式數(shù)據(jù)協(xié)議 (Distributed Data Protocol, DDP) 的協(xié)議來處理實(shí)時(shí)通信,使用 WebSockets 的新瀏覽器以及使用 Asynchronous JavaScript + XML (Ajax) 長輪詢的舊瀏覽器來支持這種協(xié)議。在這兩種情況下,瀏覽器到服務(wù)器的通信是透明的。 DDP 協(xié)議旨在處理 JavaScript Serialized Object Notation (JSON) 文檔集合,使 JSON 文檔容易創(chuàng)建、更新、刪除、查詢和訪問。因?yàn)?DDP 是一種開源協(xié)議,所以您可將它連接到任何客戶端或數(shù)據(jù)存儲。它為 MongoDB 提供了開箱即使用支持。 事實(shí)上,Meteor 提供了兩個(gè) MongoDB 數(shù)據(jù)庫:一個(gè)客戶端緩存數(shù)據(jù)庫和服務(wù)器上的一個(gè) MongoDB 數(shù)據(jù)庫。當(dāng)一個(gè)用戶更改一些數(shù)據(jù)時(shí)(例如通過單擊 Save),在瀏覽器中運(yùn)行的 JavaScript 代碼會更新本地 MongoDB 中的相應(yīng)的數(shù)據(jù)庫項(xiàng),然后向服務(wù)器發(fā)出一個(gè) DDP 請求。該代碼立即像操作已獲得成功那樣繼續(xù)運(yùn)行,因?yàn)樗恍枰却?wù)器回復(fù)。與此同時(shí),服務(wù)器在后臺更新。如果服務(wù)器操作失敗或返回一個(gè)意外結(jié)果,那么客戶端 JavaScript 代碼會依據(jù)從服務(wù)器新返回的數(shù)據(jù)立即進(jìn)行調(diào)整。這種調(diào)整稱為延遲補(bǔ)償,向用戶提供了更高的認(rèn)知速度。 顯然,甚至連 Meteor 的模板系統(tǒng)也是為簡化實(shí)時(shí)通信而設(shè)計(jì)的。在大多數(shù) Web 框架中,您可以輕松地混合使用超文本標(biāo)記語言 (HTML) 和代碼,或者與 HTML 等效的標(biāo)記,比如 HTML 抽象標(biāo)記語言 (Haml)。這使您能夠輕松地將來自數(shù)據(jù)庫的動態(tài)值插入發(fā)送給用戶的頁面中。在這之后,您應(yīng)該負(fù)責(zé)準(zhǔn)備提供一個(gè)系統(tǒng)來觀察對數(shù)據(jù)的更改,然后更新您的標(biāo)記。但是,Meteor 中的模板系統(tǒng)用于記錄訪問了模板中的哪些數(shù)據(jù),并自動回調(diào),以便在底層數(shù)據(jù)更改時(shí)調(diào)用此 HTML,使實(shí)時(shí)模板變得更加簡單快捷。 回頁首 示例:鏈接流行度競賽Meteor 的模板功能可使眾多實(shí)時(shí)應(yīng)用程序更容易編寫。例如,假設(shè)您希望創(chuàng)建一個(gè)的站點(diǎn),用戶可在其中輸入鏈接(即統(tǒng)一資源定位符,URL),并投票肯定和否決它們,而且贏得流行度競賽的 URL 會顯示在一個(gè)列表頂部。通過使用 Meteor,您可以輕松地實(shí)時(shí)編寫這樣一個(gè)應(yīng)用程序,以便用戶可在其他用戶投票時(shí)看見他們的 65 張選票。 回頁首 安裝 Meteor要安裝 Meteor,可以將 清單 1 中所示的代碼鍵入到一個(gè) Linux? 或 Mac OS? X 終端中。Meteor 不支持 Microsoft? Windows?。 清單 1. 安裝 Meteorcurl https://install. > install_meteor.sh
chmod u+x install_meteor.sh
./install_meteor.sh 現(xiàn)在您可創(chuàng)建一個(gè)新項(xiàng)目。 回頁首 創(chuàng)建一個(gè)新項(xiàng)目meteor 命令可自動化包含新項(xiàng)目創(chuàng)建過程中 Meteor 需要操作的一切內(nèi)容的。鍵入 清單 2 中所示的命令,以便創(chuàng)建一個(gè)名為 realtime_links 的項(xiàng)目。
清單 2. 創(chuàng)建您的 Meteor 項(xiàng)目meteor realtime_links
cd realtime_links Meteor 創(chuàng)建了一個(gè)目錄,其中包含一個(gè) HTML 文件、一個(gè) JavaScript 文件和一個(gè)級聯(lián)樣式表 (CSS) 文件。最后一個(gè)文件是一個(gè)標(biāo)準(zhǔn) CSS 文件,但前兩個(gè)值得討論一下。您可以從 下載 一節(jié)下載 realtime_links.html 和 realtime_links.js 文件的完整版本。 回頁首 realtime_links.html 文件清單 3 顯示了 realtime_links.html 文件的標(biāo)頭和正文片段。 清單 3. realtime_links.html 標(biāo)頭和正文片段<head>
<title>Realtime Links Demo</title>
</head>
<body>
{{> header }}
{{> link_list }}
{{> add_new_link }}
</body> 可以看到,HTML 模板的開頭非常簡單。無需擔(dān)憂如何包含 BODY 標(biāo)記、DOCTYPE 修飾符甚至 JavaScript 和 CSS 文件。Meteor 會為您處理所有這些操作。有關(guān) Meteor 的 JavaScript 和 CSS 包的更多信息,請參閱 參考資料,獲取 Meteor 網(wǎng)站的鏈接。 {{> 語法表示 “呈現(xiàn)此模板”??梢钥吹剑瑀ealtime_links.html 呈現(xiàn)了 3 個(gè)模板:
清單 4 顯示了 header 模板。 清單 4. realtime_links.html header 模板<template name="header">
<h1>The Link Collection</h1>
<p>We currently have {{collection_size}} links.</p>
</template> header 模板呈現(xiàn)了一個(gè) h1 標(biāo)記以及對集合大小的簡短描述。collection_size 方法是在 JavaScript 文件 realtime_links.js 中定義的(這將在 下一節(jié) 中詳細(xì)討論)。Meteor 自動觀察某個(gè)模板插入了哪些數(shù)據(jù)片段。所以,在更新集合大小時(shí),header 模板會自動更新。
請注意,這里使用的 {{ ... } 語法類似于 Ruby on Rails 中的 <%= ... %> 或 PHP 中的 <?= ... ?> 。它可插入任意代碼,所以能夠以這種方式插入任何有用的動態(tài)表達(dá)式。 清單 5 顯示了 link_list 模板。 清單 5. realtime_links.html link_list 模板<template name=
"link_list">
<ul>
{{#each links }}
<li> {{> link_detail }} </li>
{{/each }}
</ul>
</template> 如您所見,清單 5 中的代碼是一個(gè)鏈接列表。realtime_links.js JavaScript 文件中的 links 方法提供了此列表。系統(tǒng)會向每個(gè)鏈接呈現(xiàn)link_detail 模板。請注意,無需傳遞任何參數(shù),因?yàn)?Handlebars 的 #each 循環(huán)會將每次迭代的當(dāng)前上下文設(shè)置為當(dāng)前對象。換句話說,會將 link_detail 模板的本地方法正確解釋為每個(gè)鏈接對象的方法。 清單 6 顯示了 link_detail 模板,它控制了為每個(gè)鏈接顯示的數(shù)據(jù)。 清單 6. realtime_links.html link_detail 模板<template name="link_detail">
<div id="link-{{id}}">
<h1>{{url}}</h1>
<p><strong>Stats:</strong> up: {{thumbs_up}} down: {{thumbs_down}}
net score: {{score}}</p>
<input type="button" value="Thumbs Up"
class="thumbs_up" url="{{url}}" />
<input type="button" value="Thumbs Down"
class="thumbs_down" url="{{url}}" />
</div>
</template> h1 元素簡單地顯示當(dāng)前鏈接的 URL。然后會提供一個(gè)間斷的統(tǒng)計(jì)清單,其中包含一個(gè)鏈接被支持的次數(shù)、被否決的次數(shù)和它的凈分?jǐn)?shù)(也就是兩個(gè)值的差)。最后,有兩個(gè)按鈕:一個(gè)用于投贊成或支持票,另一個(gè)用于投反對或否決票。JavaScript 文件定義這些按鈕的行為,但是在深入介紹此主題前,還有一個(gè)模板需要了解。
清單 7 顯示了 add_new_link 模板。 清單 7.
realtime_links.html add_new_link 模板<template name="add_new_link">
<div id="new_link_form">
URL: <input id="url">
<input type="button" value="Click" id="add_url" />
</div>
</template> 該模板只是一個(gè)文本輸入字段和一個(gè)按鈕,它們共同形成了向您列表中添加新 URL 的界面。 回頁首 realtime_links.js 文件realtime_links.js 中的 JavaScript 代碼控制來自您程序的數(shù)據(jù)訪問和事件回調(diào),無論是在客戶端還是在服務(wù)器上。if (Meteor.is_client) 語句用于標(biāo)記客戶端部分,if (Meteor.is_server) 語句用于標(biāo)記服務(wù)器部分。Meteor 提供了一種保護(hù)敏感代碼的方式,阻止惡意客戶端看到源代碼。參見 參考資料 中的 Meteor 文檔鏈接,了解有關(guān)的更多細(xì)節(jié)。
清單 8 顯示了標(biāo)頭和鏈接列表幫助器函數(shù)。 清單 8. 標(biāo)頭和鏈接列表幫助器函數(shù)Template.header.collection_size = function () {
return Links.find({}).count();
};
Template.link_list.links = function () {
return Links.find({}, {sort : {score: -1} });
}; header 模板使用清單中的第一個(gè)幫助函數(shù),該函數(shù)返回 links 集合的大小。link_list 模板使用第二個(gè)幫助器函數(shù),它返回從最高分到最低分排序的所有鏈接。
清單 9 擁有對 link_detail 模板的兩個(gè)事件回調(diào)。 清單 9. link_detail 事件回調(diào) Template.link_detail.events =
{
'click input.thumbs_up' : function () {
Meteor.call('vote', this.url, 'thumbs_up');
},
'click input.thumbs_down' : function
() {Meteor.call('vote', this.url, 'thumbs_down');}
}; 每個(gè)事件回調(diào)處理一個(gè)支持或反對單擊事件。在每種情況下,它們使用客戶端上的 Meteor.call 在服務(wù)器上執(zhí)行一次函數(shù)調(diào)用??梢钥吹綇目蛻舳藢Ψ?wù)器執(zhí)行調(diào)用很簡單。例如,序列化會自動處理。 清單 10 顯示了對用戶可添加新鏈接的表單的事件回調(diào)。 清單 10. 對添加新鏈接表單的事件回調(diào) Template.add_new_link.events = {
'click input#add_url' :
dfunction () {
var new_url = $('#url').val();
var url_row = Links.findOne( {url:new_url} );
if(!url_row){
Links.insert( { url : new_url,
score: 0,
thumbs_up: 0,
thumbs_down: 0 });
}
Meteor.call('vote', url, 'thumbs_up');
}
}; 首先,該表單會嘗試找到一個(gè)具有所請求 URL 的現(xiàn)有鏈接對象。如果它找到這樣一個(gè)對象,那么它會將該請求統(tǒng)計(jì)為對這個(gè)現(xiàn)有鏈接對象的一次投票。如果未找到,那么它會創(chuàng)建一個(gè)新鏈接對象,并對這個(gè)新對象執(zhí)行一次 thumbs_up 投票。 這部分代碼演示了 Meteor 作為一種一流技術(shù)的優(yōu)點(diǎn)和不足,它還不適合用于生產(chǎn)。如您所見,客戶端可在 links 集合上調(diào)用 insert 。盡管這對開發(fā)人員很有用,但從安全角度講,這是一個(gè)問題。幸運(yùn)的是,開發(fā)人員正在積極研究該代碼的一個(gè) auth 分支,這個(gè)分支可以實(shí)現(xiàn)強(qiáng)大的身份驗(yàn)證功能,同時(shí)仍然保持 Meteor 富有吸引力的很多強(qiáng)大功能和靈活性。 此外,需要認(rèn)識到 Meteor 目前沒有實(shí)現(xiàn)所有 MongoDB 功能。例如,Meteor 不支持 MongoDB upsert,該操作插入新數(shù)據(jù)或修改舊數(shù)據(jù)。如果 Meteor 支持 upsert,那么您可以編寫 清單 11 中所示的函數(shù)。 清單 11. 一個(gè)使用 upsert 的假想的添加新鏈接表單事件回調(diào) Template.add_new_link.events = {
'click input#add_url' : function () {
var new_url = $('#url').val();
Links.update( { url : new_url},
{ $set: {url : new_url},
$inc: { votes : 1 } } , true );
}
}; 如您所見,使用 upsert 的代碼更短。它運(yùn)行得可能更快,因?yàn)樗鼉H需要與服務(wù)器執(zhí)行一次往返傳輸。如果順利的話,Meteor 很快就會實(shí)現(xiàn)對 upsert 和其他新功能的支持。 清單 12 中的代碼在服務(wù)器上運(yùn)行。它是一個(gè)可由客戶端代碼調(diào)用的方法。此方法(vote )允許客戶端對一個(gè)流行的 URL 投 thumbs_up 或 thumbs_down 票。它使用 Mongo 的 $inc 運(yùn)算符遞增適當(dāng)?shù)耐镀庇?jì)數(shù)器。它還在必要時(shí)遞增或遞減總數(shù)。Meteor.startup 方法僅支持代碼在服務(wù)器啟動時(shí)運(yùn)行。Meteor.methods 函數(shù)然后定義可在客戶端上調(diào)用 Meteor.call 的函數(shù),如前面的 清單 9 中所述。 清單 12. 服務(wù)器端的 vote 方法代碼if (Meteor.is_server) {
Meteor.startup(function () {
Meteor.methods({
vote: function (url, field){
new_obj = { $inc: { } };
if(field =='thumbs_up'){
new_obj['$inc']['thumbs_up'] = 1;
new_obj['$inc']['score'] = 1;
}else{
new_obj['$inc']['thumbs_down'] = 1;
new_obj['$inc']['score'] = -1;
}
Links.update( { url : url}, new_obj );
}
});
});
} 與 清單 10 一樣,您可在客戶端上運(yùn)行 清單 12 中的代碼。但是,出于演示目的,將會在服務(wù)器上運(yùn)行該代碼。隨著 Meteor 的安全模型得到改進(jìn),可能會將敏感的代碼開發(fā)為服務(wù)器端函數(shù),如下面清單所示。 回頁首 查看您的應(yīng)用程序的實(shí)際效果現(xiàn)在可啟動您的 Meteor 應(yīng)用程序(如 清單 13 中所示)并查看它的實(shí)際效果。 清單 13. 啟動您的系統(tǒng)在啟動后,Meteor 會在端口 3000 上運(yùn)行。打開一個(gè) Web 瀏覽器并訪問 http://localhost:3000/。 如果在 Add a URL 下輸入一個(gè) URL 并單擊 Add,則看到一個(gè) URL 和評分 one 。然后您可以單擊 Thumbs Up 或 Thumbs Down 按鈕對該 URL 進(jìn)行投票。這會實(shí)時(shí)進(jìn)行,而不會刷新頁面。如果打開一個(gè)新 Web 瀏覽器,可在另一個(gè)窗口中執(zhí)行相同操作,這時(shí)第一個(gè)窗口會立即更改。 當(dāng)添加多個(gè) URL 時(shí),可以看到一個(gè)具有最高評分的 URL(分?jǐn)?shù)被定義為支持票數(shù)減去反對票數(shù))顯示在最頂部。在投支持或反對票時(shí),URL 會隨著其評分更改而在列表中向上或向下移動。這是實(shí)時(shí)進(jìn)行的,在輸入投票時(shí),多個(gè)瀏覽器上的多個(gè)用戶都會收到相同的數(shù)據(jù)。 回頁首 結(jié)束語Meteor 是一個(gè)極具優(yōu)勢的 Web 框架,它包含了許多有趣的概念。它對實(shí)時(shí)數(shù)據(jù)的支持既富有吸引力又至關(guān)重要,特別是在考慮到其他技術(shù)實(shí)時(shí)支持充其量是一種事后行為時(shí)。隨著實(shí)時(shí)交互變得對未來的 Web 更加重要,Meteor 輕松快速地實(shí)時(shí)處理復(fù)雜數(shù)據(jù)集的能力也將變得更加重要。
回頁首 下載
|