2013年9月25日 星期三

Ejs page scope直接使用session物件的方式

在操作ExpressJS的Ejs View Engine時候
發現針對頁面上的操作並不是那麼的順心
舉個例子:
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(locales['user']) { .... %>

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