接著上次的 Part 1 這回繼續寫樣板與資料庫的部份。
使用樣板
每次都要寫一大堆 .html 檔案,當你的檔案越來越多的時候,改起來就相對麻煩。而且,我們也想把一些變數傳進去用,這個時候樣板引擎就是個解決方法。Express 所支援的樣板引擎相當多元,
Haml
Jade
EJS
CoffeeKup
jQuery Templates
這裡有剛剛提到的 EJS 跟 Jade,而其實我現在慢慢地再改用 CoffeeKup,所以,這裡我挑了 Jade 來作一些簡單介紹。喔,為什麼不是介紹 CoffeeKup?因為這樣我還要再講一次 CoffeeScript,所以我還是講 Jade 就好了(飄走
我們在 Express 要怎麼使用他呢?請看底下簡單範例,
var express = require("express"),
app = express.createServer(express.logger());
app.configure(function() {
app.set("views", __dirname + "/views");
app.set("view engine", "jade");
});
app.get("/", function(req, res) {
res.sendfile(__dirname + '/index.html', function(err) {
if (err) res.send(404);
});
});
app.get(/(.*)\.(jpg|gif|png|ico|css|js|txt)/i, function(req, res) {
res.sendfile(__dirname + "/" + req.params[0] + "." + req.params[1], function(err) {
if (err) res.send(404);
});
});
port = process.env.PORT || 3000;
app.listen(port, function() {
console.log("Listening on " + port);
});
我們將 View 的資料夾設定在 views 底下,然後將樣板引擎指定為 jade,這樣,我們就可以開始寫一個 index.jade 這樣的樣板檔案了。請記得,檔案是放在 views 資料夾下面的,
h1 "Hello NodeJS"
這樣就可以了嗎?當然不是,我們還要修改一下 web.js 才行,
var express = require("express"),
app = express.createServer(express.logger());
app.configure(function() {
app.set("views", __dirname + "/views");
app.set("view engine", "jade");
});
app.get("/", function(req, res) {
res.render("index", {layout: false});
});
app.get(/(.*)\.(jpg|gif|png|ico|css|js|txt)/i, function(req, res) {
res.sendfile(__dirname + "/" + req.params[0] + "." + req.params[1], function(err) {
if (err) res.send(404);
});
});
port = process.env.PORT || 3000;
app.listen(port, function() {
console.log("Listening on " + port);
});
這樣就可以運行了,使用樣板的好處是,你不用一直重新啟動 node 的服務,只要改了樣板內容,他就會做改變。並不會因為他是樣板引擎而需要重新啟動 node 的服務。那,我要怎麼傳變數進去呢?請看,
app.get("/", function(req, res) {
res.render("index", {
layout: false,
nickname: "閃光洽"
});
});
樣板要怎麼接收呢?
h1= nickname
關於 Jade 還有相當多的變化可用,在他的 gitHub 說明中寫得還算詳盡,包含了陣列、邏輯判斷、字串處理等等。想要知道更多詳細操作的人,可以去他們的 gitHub 看看。
WebSocket
因為新的瀏覽器開始實做 websocket 的部份(我沒有說 IE),所以 NodeJS 在一開始就對這一塊有部份的支援,不過因為當初改版頻繁,所以有些東西其實寫完之後,改版就爛掉的事情時常發生,也被人詬病。
BUT!
救星出現了,他叫做 socket.io,你應該很好奇他要做什麼?舉個簡單的例子,聊天室那麼多人一來一往,訊息即時性的發佈與傳遞,就可以靠他來完成。其實 NodeJS 本身就有這種機制,只是當初並不完善,而有這些模組的助力,讓這些事情變簡單而已。
當然是要安裝的,
$ npm install socket.io
然後就請看官方的範例(喂,其實我說正格的,官方的範例相當完整。這個模組其實只是替我們做掉了 NodeJS 關於 Event 這個部份而已,他並沒有很囉唆的做很多事情。
而且他的好處是,我也可以拿去給前端用,就此,聊天室一來一往的傳送就可以串起來了。當然,WebSocket 可以做的事情不只聊天室,只是舉這個例子比較容易理解而已。所以我貼一下官方範例,應該不過份吧 XD
var express = require("express"),
app = express.createServer(express.logger()),
io = require("socket.io").listen(app);
app.configure(function() {
app.set("views", __dirname + "/views");
app.set("view engine", "jade");
});
app.get("/", function(req, res) {
res.render("index", {layout: false});
});
app.get(/(.*)\.(jpg|gif|png|ico|css|js|txt)/i, function(req, res) {
res.sendfile(__dirname + "/" + req.params[0] + "." + req.params[1], function(err) {
if (err) res.send(404);
});
});
io.sockets.on("connection", function (socket) {
socket.emit("front-end", { hello: "world" });
socket.on("my other event", function (data) {
console.log(data);
});
});
port = process.env.PORT || 3000;
app.listen(port, function() {
console.log("Listening on " + port);
});
我們的 index.jade 也要改一下,
!!! 5
html
head
meta(charset="utf-8")
title "Hello Socket.IO"
script(src="/socket.io/socket.io.js")
body
h1= nickname
script
var socket = io.connect();
socket.on("front-end", function (data) {
console.log(data);
socket.emit("my other event", {my: data});
});
這個 index.jade 也改太多了吧,其實我就只是把他寫得比較規矩一點而已,沒有改很多啦。這個範例做了兩件事,
主機監聽了一個叫做 my other event 事件。
當連入 / 的時候,主機觸發了 front-end 這個事件。
用戶端監聽了一個叫做 front-end 事件。
當該事件觸發時,會再觸發 my other event 這個事件。
這樣知道他們兩個人之間發生什麼事情了嗎?其實就像是打來打去鬧來鬧去戳來戳去的小情侶而已嘛。
關於資料庫
當然是用目前最熱門的 Mongo 資料庫,其實你要用 MySQL 也不是不行,
不過這裡以 MongoDB 為例子,當然,你的系統需要安裝 MongoDB,才能用囉!
$ npm install mongodb
應用程式的部份稍做修改,
var express = require("express"),
app = express.createServer(express.logger()),
io = require("socket.io").listen(app),
mongodb = require("mongodb"),
mongodbServer = new mongodb.Server("localhost", 27017, {
auto_reconnect: true,
poolSize: 10
}),
db = new mongodb.Db("mydatabase", mongodbServer);
app.configure(function() {
app.set("views", __dirname + "/views");
app.set("view engine", "jade");
});
app.get("/", function(req, res) {
res.render("index", {layout: false});
});
app.get(/(.*)\.(jpg|gif|png|ico|css|js|txt)/i, function(req, res) {
res.sendfile(__dirname + "/" + req.params[0] + "." + req.params[1], function(err) {
if (err) res.send(404);
});
});
io.sockets.on("connection", function (socket) {
socket.emit("front-end", { hello: "world" });
socket.on("my other event", function (data) {
console.log(data);
db.open(function() {
db.collection("test", function(error, collection) {
collection.insert({
data: data
});
db.close();
});
});
});
});
port = process.env.PORT || 3000;
app.listen(port, function() {
console.log("Listening on " + port);
});
以上的例子,是當用戶端觸發了 my other event 的時候,會將用戶傳來的 data 儲存在 mydatabase 這個資料庫中,且儲存的集合是 test,欄位的名稱叫做 data。
當然,例子太簡單就不好玩了,這裡面有一個 Bug。
這裡有一篇關於 NodeJS 與 MongoDB 的文章,可以參考:
NodeJS 與 MongoDB 的邂逅
小結
NodeJS 對這個世界的衝擊當然不只如此而已,Javascript 變成顯學這件事情可能也是始料未及。不過,這些事情總是會讓人興奮的,就端看未來會如何去發展了!
結果到最後我真的沒提到 CoffeeScript