ejs

EJS是Express顯示層的一個外掛,可以提供html編輯方式的語法,讓操作view部分的顯示更為方便與直覺。

套件資訊

Installation

npm install ejs

如果專案的初始化是使用express的話,可以透過下面方式直接載入ejs模組

express -e [專案名稱]

Sample Usage

設定Express的view engine使用ejs模組

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path');

var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
//採用ejs作為view engine
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

透過route的抽離,定義新的route叫做index.js,並透過res.render將參數與顯示頁面定義於route上

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

頁面上的操作部分,可以透過<%=...%>, <%-...%>, <%...%>等嵌入Node.js的操作語法

<%= title %>
Welcome to <%= title %>

View template module - express-partials

Github: https://github.com/publicclass/express-partials

新版的express已經將template系統改寫,原本使用在res.render('...', {layout:'somelayout'})需要另外載入express-partials模組方能使用,載入方式如下:

var express = require('express')
  , partials = require('express-partials')
  , app = express();

app.use(partials());

partial使用上預設是使用layout.ejs作為預設template,因此在未指定時,系統將抓$project/views/layout.ejs檔案作為樣板,而需要指定特別樣板時可以在route中這樣使用:

app.get('/test', function(req, res) {
  ...
  res.render('page_name', {layout: 'your_layout', obj: 'your objects...'});
});

進階操作 - Scope參數的操控

當app.js中做一個route希望能夠將值往前端(.ejs)帶,但是前端implement了express-partials的模組,希望把頁面用template的方式組織起來,並且在template page中會用到一部分的參數... 假設有時個route用到這個template,則每個route都必須把參數設定進去,否則後端會接收到"not defined"的錯誤訊息...

上面例子的片段程式碼如下:

[app.js]

app.get('/', function(req, res){
  res.render('index', { title: 'my express page' });
});

[index.ejs]

<% if(user) { %>
<%= user %>
<% } %>

執行時候會有Exception:

...(skip)
user is not defined
...(skip)

這部份的錯誤應該是Ejs在render page時候造成的,它直接throw Exception而會造成page終止render,在遍尋不著比較好的方法時,從某篇文章找到一些蛛絲馬跡...

原來Ejs使用"locals"這個物件來包裝頁面上會用到的所有參數,而經過ejs的scriptlet tag包裝起來的部分,可以直接使用locals裡面的參數,也就是說上面的app.js做page render時候:

res.render('index', { title: 'my express page' })

相當於把title這個參數與ejs頁面的locals變數做整合 亦即ejs頁面操作:

<%=title%>

<%=locals.title%>

是相等的,但是直接操作title屬性時候,會被ejs compile成runtime exception,這導致如果在ejs中執行下面判斷會出錯;

<% if(user) { .... %>

因為實際上locals.user不存在,且ejs compiler會將不存在的狀況throw exception...

解決方式,直接使用locals來判斷裡面是否有user這個變數...,因此改寫上面的判斷後:

<% if(locals['user']) { .... %>

應該就可以正常運作...

進階操作 - 與session的結合

在ExpressJS中,使用Ejs view engine時,發現session不能再ejs page中直接取用,所有參數都必須靠render時候傳遞過去...跟asp, jsp等scriptlet language操作上有明顯的不同...@@

為了達到可以在ejs中直接取用,這邊可以使用ejs page的locals變數,locals變數在route設定時候可以使用res.locals來取出,這時候只要將它與req.session做串連(res.locals.session = req.session)即可讓前端的ejs page直接透過<%=locals.session%>或是<%=session%>的方式來操作session...

而如果要在每一個route中設定res.locals.session,這樣也太麻煩... 我們可以透過app.use的方式來設定:

app.use(function(req, res, next){
  res.locals.session = req.session;
  next();
});

這樣所有的route在執行的時候都會先跑過一次這個動作,所以在使用時候可以這樣:

[app.js]

app.get('/', function(req, res) {
  req.session.user = {name: 'simon'}
  ...(skip)
});

[view/index.ejs]

...(skip)
<%=session.user? 'got user: '+session.user.name : 'no user...'%>
...(skip)

這時候從ejs取用session的物件就單純多了 :D

results matching ""

    No results matching ""