NodeJS框架Express的模板视图机制分析


Posted in NodeJs onJuly 19, 2011

模板引擎

Express支持许多模板引擎,常用的有:

  • haml 的实现Haml
  • haml.js 接替者,同时也是Express的默认模板引擎Jade
  • 嵌入JavaScript模板EJS
  • 基于CoffeeScript的模板引擎CoffeeKup
  • 的NodeJS版本jQuery模板引擎

视图渲染(view randering)

视图的文件名默认需遵循“<name>.<engine>”的形式,这里<engine>是要被加载的模块的名字。比如视图layout.ejs就是在告诉视图系统要require(‘ejs'),被加载的模块必须输出exports.compile(str, options)方法,并要返回一个函数来遵守Express的模板接口约定。我们也可以使用app.register()来映射模板引擎到其它文件扩展名,从而实现更灵活的模板引擎行为,如此一来就可以实现“csser.html”可以被ejs引擎所渲染。

下面我们将用Jade引擎来渲染index.html,因为我们没有设置layout:false,index.jade渲染后的内容将被作为body本地变量传入layout.jade。

<SPAN style="FONT-SIZE: 13px">app.get('/', function(req, res){ 
res.render('index.jade', { title: 'CSSer, 关注Web前端技术!' }); 
}); 
</SPAN>

新增的“view engine”设置可以指定默认模板引擎,如果我们想使用jade可以这样设置:
<SPAN style="FONT-SIZE: 13px">app.set('view engine', 'jade'); 
</SPAN>

于是我们就可以通过下面的方式:
<SPAN style="FONT-SIZE: 13px">res.render('index'); 
</SPAN>

代替如下方式:
<SPAN style="FONT-SIZE: 13px">res.render('index.jade'); 
</SPAN>

当“view engine”设置后,模板的扩展名就成了可选项,同时我们还可以混合匹配多模板引擎:
<SPAN style="FONT-SIZE: 13px">res.render('another-page.ejs'); 
</SPAN>

Express同时提供了视图选项设置,这些设置会在每次视图渲染后应用,比如你并不经常使用layouts,就可以这样设置:
<SPAN style="FONT-SIZE: 13px">app.set('view options', { 
layout: false 
}); 
</SPAN>

如果需要,这些设置可以在后续的res.render()调用中被覆盖:
<SPAN style="FONT-SIZE: 13px">res.render('csser-view.ejs', { layout: true }); 
</SPAN>

可以通过指定一个路径的方式来实现用自己的layout来代替系统默认的,比如如果我们将“view engine”设置为jade并且自定义了一个名为“./views/mylayout.jade”的layout,我们可以这样使用它:
<SPAN style="FONT-SIZE: 13px">res.render('page', { layout: 'mylayout' }); 
</SPAN>

否则必须指定扩展名:
<SPAN style="FONT-SIZE: 13px">res.render('page', { layout: 'mylayout.jade' }); 
</SPAN>

这些路径也可以是绝对路径:
<SPAN style="FONT-SIZE: 13px">res.render('page', { layout: __dirname + '/https://3water.com/mylayout.jade' }); 
</SPAN>

这方面较好的例子就是自定义ejs模板的开始和关闭的标记:
<SPAN style="FONT-SIZE: 13px">app.set('view options', { 
open: '{{', 
close: '}}' 
}); 
</SPAN>

局部视图(View Partials)
Express视图系统原生支持局部和集合视图,这称作微型视图,主要用于渲染一个文档片段。比如与其在视图中循环显示评论,不如使用局部集合(partial collection):
<SPAN style="FONT-SIZE: 13px">partial('comment', { collection: comments }); 
</SPAN>

如果不需要其它选项或本地变量,我们可以省略对象而简单的传入评论数组,这和上面的示例是一样的:
<SPAN style="FONT-SIZE: 13px">partial('comment', comments); 
</SPAN>

当使用局部集合时,支持一些“魔术”本地变量:

  • firstInCollection 当为第一个对象时该值为true
  • indexInCollection 集合中对象的索引值
  • lastInCollection 当为最后一个对象时为true
  • collectionLength 集合的长度

Local variables passed (or generated) take precedence, however locals passed to the parent view are available in the child view as well. So for example if we were to render a blog post with partial(‘blog/post', post) it would generate the post local, but the view calling this function had the local user, it would be available to the blog/post view as well.

传入(或生成)的本地变量优先,但传入父视图的本地变量在子视图仍有效。因此如果我们用partial(‘blog/post', post)来渲染博客日志时,将生成post的本地变量,但调用本函数的视图拥有本地用户,它在blog/post视图依然有效。(一回注:这段翻译感觉有问题,请高人指点)。

性能提示:当使用局部集合渲染100长度的数组就意味着需要渲染100次视图,对于简单的集合你可以将循环内联,而不要使用局部集合,这样可以减少系统开销。

视图查找(View Lookup)

视图查找是相对于父视图进行的,比如我们有一个名为“views/user/list.jade”的页面视图,如果在该视图中调用 partial(‘edit'),视图系统将会尝试查找并加载“views/user/edit.jade”,而partial(‘.. /messages')将加载“views/messages.jade”。

视图系统还支持索引模板,这样你就可以使用一个同名的目录。比如,在一个路由中我们执行res.render(‘users'),这将指向“views/users.jade”或者“views/users/index.jade”。

当使用上面的索引视图时,我们可以通过partial(‘users')从同名目录下引用“views/users/index.jade”,同时视图系统会尝试“../users/index”,这能减少我们调用partial(‘index')的需要。

NodeJs 相关文章推荐
我的NodeJs学习小结(一)
Jul 06 NodeJs
NodeJs读取JSON文件格式化时的注意事项
Sep 25 NodeJs
详解nodejs 文本操作模块-fs模块(二)
Dec 22 NodeJs
nodejs根据ip数组在百度地图中进行定位
Mar 06 NodeJs
nodejs入门教程三:调用内部和外部方法示例
Apr 24 NodeJs
Nodejs进阶之服务端字符编解码和乱码处理
Sep 04 NodeJs
详解nodejs通过代理(proxy)发送http请求(request)
Sep 22 NodeJs
nodejs分离html文件里面的js和css的方法
Apr 09 NodeJs
M2实现Nodejs项目自动部署的方法步骤
May 05 NodeJs
nodejs读取图片返回给浏览器显示
Jul 25 NodeJs
nodejs dgram模块广播+组播的实现示例
Nov 04 NodeJs
nodeJs的安装与npm全局环境变量的配置详解
Jan 06 NodeJs
golang、python、php、c++、c、java、Nodejs性能对比
Mar 12 #NodeJs
PHPStorm 2020.1 调试 Nodejs的多种方法详解
Sep 17 #NodeJs
nodejs实用示例 缩址还原
Dec 28 #NodeJs
nodejs 后缀名判断限制代码
Mar 31 #NodeJs
用nodejs访问ActiveX对象,以操作Access数据库为例。
Dec 15 #NodeJs
NodeJS 模块开发及发布详解分享
Mar 07 #NodeJs
nodejs入门详解(多篇文章结合)
Mar 07 #NodeJs
You might like
php file_get_contents函数轻松采集html数据
2010/04/22 PHP
php获取指定日期之间的各个周和月的起止时间
2014/11/24 PHP
thinkphp备份数据库的方法分享
2015/01/04 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
2015/10/19 PHP
Docker搭建自己的PHP开发环境
2018/02/24 PHP
php中对象引用和复制实例分析
2019/08/14 PHP
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
模仿JQuery sortable效果 代码有错但值得看看
2009/11/05 Javascript
jQuery图片滚动图片的效果(另类实现)
2013/06/02 Javascript
js模仿windows桌面图标排列算法具体实现(附图)
2013/06/16 Javascript
javascript history对象(历史记录)使用方法(实现浏览器前进后退)
2014/01/07 Javascript
JavaScript利用构造函数和原型的方式模拟C#类的功能
2014/03/06 Javascript
javascript版的in_array函数(判断数组中是否存在特定值)
2014/05/09 Javascript
JavaScript动态修改弹出窗口大小的方法
2015/04/06 Javascript
JavaScript中字符串分割函数split用法实例
2015/04/07 Javascript
基于JS判断iframe是否加载成功的方法(多种浏览器)
2016/05/13 Javascript
js判断输入字符串是否为空、空格、null的方法总结
2016/06/14 Javascript
详解JS中定时器setInterval和setTImeout的this指向问题
2017/01/06 Javascript
jquery中done和then的区别(详解)
2017/12/19 jQuery
node.js中路由,中间件,ge请求和post请求的参数详解
2017/12/26 Javascript
详解微信小程序支付流程与梳理
2019/07/16 Javascript
解决layui动态加载复选框无法选中的问题
2019/09/20 Javascript
[52:52]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第三局
2016/02/27 DOTA
Python中输出ASCII大文字、艺术字、字符字小技巧
2015/04/28 Python
Python 转换文本编码实现解析
2019/08/27 Python
Django关于admin的使用技巧和知识点
2020/02/10 Python
Python使用graphviz画流程图过程解析
2020/03/31 Python
html5简介及新增功能介绍
2020/05/18 HTML / CSS
什么叫应用程序域?什么是受管制的代码?什么是强类型系统?什么是装箱和拆箱?
2016/08/13 面试题
迎八一活动主题
2014/01/31 职场文书
技术总监管理职责范本
2014/03/06 职场文书
生活小常识广播稿
2014/09/16 职场文书
教师调动申请报告
2015/05/18 职场文书
pytorch 如何使用float64训练
2021/05/24 Python
Pytest中skip skipif跳过用例详解
2021/06/30 Python
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript