Node.js 使用jade模板引擎的示例


Posted in Javascript onMay 11, 2018

在“Node.js开发入门——Express安装与使用”里,我们曾经使用express generator创建了一个HelloExpress网站,express工具为我们生成了基本的目录结构、模板、stylesheet、routers等。虽然那只是一个简单的HelloWorld类的小东西,可里面包含的内容还是有些多了,为了更好的理解Express所支持的jade模板引擎的用法,我们这次提供一个手动创建的小网站,可以显示来访者的IP,并对访问进行计数。

安装jade

npm install -g jade

执行上面的命令,全局安装。

Visitor网站

第1步,在myprojects目录下创建一个Visitor目录。

第2步,把下面的代码保存在package.json文件里:

{
 "name": "Visitor",
 "version": "0.0.0",
 "private": true,
 "dependencies": {
 "express": "~4.13.1",
 "jade": "~1.11.0",
 }
}

这个json文件描述了我们的Visitor网站的一些信息,最重要的部分是依赖。我们要使用express和jade。

var express = require('express');
var app = express();

var counter = 0;

// view engine setup
app.set('views', './views');
app.set('view engine', 'jade');
app.engine('jade', require('jade').__express);

app.get('/', function(req, res) {
 counter++;
 app.locals.counter = counter.toString();
 res.render('index', {ip: req.ip});
});

app.listen(3000);

app.locals.title = "Welcome to Visitor";
app.locals.counter = "0";

app.js文件是我们网站的入口。

第4步,创建一个views目录,在里面创建一个模板文件index.jade,内容如下:

doctype html
html
 head
 title= title
 body
 h1= title
 p Hello, #{ip}
 p You're the #{counter} visitor.

第5步,在Visitor目录里执行“npm install”,安装依赖。

第6步,在Visitor目录里执行“node app.js”,启动网站。

最后呢,就可以在浏览器里访问了,地址栏里输入“http://localhost:3000”即可,刷新几次,你可能会看到下面的界面:

Node.js 使用jade模板引擎的示例

这个简单的Visitor网站,和之前的HelloWorld、HelloExpress都不太一样了,它有了一些动态的内容。接下来我们就来看看这一切是如何发生的。

express与模板引擎

我在Visitor里使用了jade模板引擎,类似的还有ejs以及很多,可以访问这里来了解:https://github.com/joyent/node/wiki/Modules。

模板引擎使用模板文件来动态生成HTML文件,在生成时又可以按照一定的规则将应用程序里的数据整合进HTML文件。这样,我们既避免了手动编写HTML的繁琐(相对使用模板而言),又能生成具有动态内容的网页。

Express和Jade结合得比较好,我们来看看怎么配置它。

Express配置jade

Express服务器的行为可以通过一些设置选项来控制,这些选项可以通过express对象的set(setting, value)、enable(setting)和disable(setting)来设置。具体支持哪些设置,可以看这里http://expressjs.com/4x/api.html。我们的Visitor只用到了“view engine”和“views”。

“view engine”选项用来设置要使用的引擎,Visitor的代码如下:

app.set('view engine', 'jade');

“views”选项用来设置模板文件所在目录,Visitor的代码如下:

app.set('views', './views');

我在这里简单的使用了相对路径,更好的做法是使用path模块,根据全局变量__dirname来拼接。__dirname指当前正在执行的脚本所在的目录,对我们的Visitor示例来讲,就是app.js所在的那个目录。代码可能是这样的:

var path = require('path');
path.join(__dirname, 'views');

express默认会根据模板文件的扩展名来使用对应的引擎。对于*.jade文件,express内部会调用下面的语句:

app.engine('jade', require('jade').__express);

所以,我们的app.js,实际上也可以去掉这行代码,结果是一样的。

本地对象

我们可以在模板文件里包含动态数据,这些动态数据来自应用程序。我们可以使用express对象的locals对象来存储本地变量。下面的代码就存储了标题和访问计数:

app.locals.title = "Welcome to Visitor";
app.locals.counter = "0";

jade模板文件里可以直接访问express对象的locals对象的属性。我在app.js里设置的title和counter,在index.jade模板文件引用了它们。

现在我们来看这行代码:

res.render('index', {ip: req.ip});

它调用express的Response对象的render方法来渲染模板文件,并且传递了一个本地对象。render方法原型:

res.render(view [, locals] [, callback])

res.render方法渲染一个view并且把渲染生成的HTML字符串发送给客户端。res的API参考在这里http://expressjs.com/4x/api.html。

Response对象也有一个locals对象,它和app.locals的区别是,res的locals只在当前渲染的view内有效,而app.locals是全局的。

另外render方法的可选参数locals,也可以定义本地变量对象,传递给view。我在代码里把ip传了过去。

在jade文件里,常见的有两种方式可以调用由应用程序传入的本地变量:

  1. #{表达式}
  2. 标签=表达式

前面的index.jade模板文件里,对于页面标题,我们这么用的:

title= title

title是jade用来定义HTML文档title的标签。

对于body里的一级标题,我们这么用的(h1是jade用来定义HTML一级标题的标签):

h1= title

这都是属于“标签=表达式”这种调用方式,这种方式通常用在一行jade代码的开始,也就是标签开始的地方。而“#{表达式}”这种方式的好处是可以插入到jade模板文件的任意地方。比如:

p Hello, #{ip}
p You're the #{counter} visitor.

我们也可以将“h1= title”修改为“h1 #{title}”,效果一样。

jade引擎简介

jade使用一些标签来标记如何生成HTML,jade模板文件看起来很不像HTML文件,但它的模板文件小而整洁。使用jade,需要了解它都支持哪些标签,这个可以直接去看jade-lang,那里最详细也最权威,我们这里只介绍index.jade文件用到的那些标签。

关于jade,有两篇文章不错,可以看看,https://cnodejs.org/topic/5368adc5cf738dd6090060f2和https://3water.com/article/139936.htm,后面这篇文章是网友根号三写的一个关于jade的系列文章的开篇,整个系列里的文章都值得一看。

HTML文档的开始通常是文档声明,对应到jade模板文件里,就是doctype html。还有其它的文档类型,比如xml,可以写作doctype xml。更多请参考http://jade-lang.com/reference/doctype/。

jade有很多标签,用于生成HTML对应的标签。比如html对应,head对应,body对应,p对应,title对应,这也是我们的index.jade用到的所有标签了。通常我们在HTML里使用的标签写法,去掉尖括号就成了jade里可用的标签,比如对应jade里的div。

HTML标签往往可以设置name、id、class等属性,在jade里,是通过tag(attr=value)这种形式表示的。比如div(class=”view-container”),又比如input(type=”checkbox”)。

关于jade标签,这篇文章https://3water.com/article/139942.htm说得很好,请参考。

测试jade模板文件

一开始用jade模板,记不全它的标签,也经常不知道自己的写的模板文件生成的html文档是否正确。还好安装jade后,有一个命令行工具jade,可以用来验证模板文件。

jade的用法如下:jade [options] [dir|file …]

jade命令有很多选项,可以执行“jade -h”查看。要验证模板文件,最简单的办法就是使用jade工具生成为html文档。命令如下:

jade xxx.jade

执行上面的命令,就会在当前目录下生成一个与模板文件同名的html文档。不过格式很难读,完全是一坨屎挤在一起。加上 -P(?pretty) 就好了。这样:

jade -P xxx.jade

比如我们有这么一个使用了AngularJS的模板文件scope_template.jade,内容如下:

doctype html
html(ng-app="myApp")
 head
 title= title
 link(rel='stylesheet', href='/stylesheets/style.css')
 body
 div(ng-controller="SimpleTemplate")
 | ValueA: 
 input(type="number" ng-model="valueA")
 br
 | ValueB: 
 input(type="number" ng-model="valueB")
 br
 br
 | Expression Value: {{valueA + valueB}}
 br
 br
 input(type="button" ng-click="addValues(valueA, valueB)" value="Click to Add Values {{valueA}} & {{valueB}}")
 br
 | Clicked Value: {{valueC}}
 br

 script(src="/javascripts/angular-1.4.3.min.js")
 script(src="/javascripts/scope_template.js")

运行“jade -P scope_template.jade”命令会生成scope_template.html文件,内容如下:

<!DOCTYPE html>
<html ng-app="myApp">
 <head>
 <title></title>
 <link rel="stylesheet" href="/stylesheets/style.css" rel="external nofollow" >
 </head>
 <body>
 <div ng-controller="SimpleTemplate">ValueA: 
 <input type="number" ng-model="valueA"><br>ValueB: 
 <input type="number" ng-model="valueB"><br><br>Expression Value: {{valueA + valueB}}<br><br>
 <input type="button" ng-click="addValues(valueA, valueB)" value="Click to Add Values {{valueA}} & {{valueB}}"><br>Clicked Value: {{valueC}}<br>
 </div>
 <script src="/javascripts/angular-1.4.3.min.js"></script>
 <script src="/javascripts/scope_template.js"></script>
 </body>
</html>

需要提一下,我们既可以用jade编写完整的HTML文档,也可以编写符合HTML语法的局部模板。比如下面的jade文件:

div(class="admin-user")
 p 添加用户
 table
 tr
 td
 label 用户名:
 td
 input(type="text" name="add_username")
 tr
 td
 label 密码:
 td
 input(type="text" name="add_password") 
 tr
 td(colspan='2' align="right")
 input(type="submit" value="增加")

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js 无提示关闭浏览器页面的代码
Mar 09 Javascript
JavaScript 原型与继承说明
Jun 09 Javascript
js页面跳转的常用方法整理
Oct 18 Javascript
jQuery插件datatables使用教程
Apr 21 Javascript
JavaScript 数组中最大最小值
Jun 05 Javascript
通过jquery实现页面的动画效果(实例代码)
Sep 18 Javascript
jQuery Easyui Treegrid实现显示checkbox功能
Aug 08 jQuery
JavaScript实现焦点进入文本框内关闭输入法的核心代码
Sep 20 Javascript
微信小程序开发之map地图组件定位并手动修改位置偏差
Aug 17 Javascript
Vue修改项目启动端口号方法
Nov 07 Javascript
axios如何取消重复无用的请求详解
Dec 15 Javascript
Javascript实现秒表计时游戏
May 27 Javascript
Node.js Express安装与使用教程
May 11 #Javascript
Node.js创建HTTP文件服务器的使用示例
May 11 #Javascript
Node.js引入UIBootstrap的方法示例
May 11 #Javascript
Node.js使用Angular简单示例
May 11 #Javascript
Node.js 使用AngularJS的方法示例
May 11 #Javascript
Angular使用动态加载组件方法实现Dialog的示例
May 11 #Javascript
详解JavaScript中的数组合并方法和对象合并方法
May 11 #Javascript
You might like
?生?D片??C字串
2006/12/06 PHP
php安全开发 添加随机字符串验证,防止伪造跨站请求
2013/02/14 PHP
总结PHP删除字符串最后一个字符的三种方法
2016/08/30 PHP
PHP 实现浏览记录并按日期分组
2017/05/11 PHP
PHP中Static(静态)关键字功能与用法实例分析
2019/04/05 PHP
php函数式编程简单示例
2019/08/08 PHP
laravel框架select2多选插件初始化默认选中项操作示例
2020/02/18 PHP
JS图片浏览组件PhotoLook的公开属性方法介绍和进阶实例代码
2010/11/09 Javascript
JavaScript使用指针操作实现约瑟夫问题实例
2015/04/07 Javascript
实例讲解JS中setTimeout()的用法
2016/01/28 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
2016/03/08 Javascript
获取input标签的所有属性的方法
2016/06/28 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
js改变html的原有内容实现方法
2016/10/05 Javascript
js 能实现监听F5页面刷新子iframe 而父页面不刷新的方法
2016/11/09 Javascript
JavaScript中boolean类型之三种情景实例代码
2016/11/21 Javascript
vue loadmore组件上拉加载更多功能示例代码
2017/07/19 Javascript
js定时器实现倒计时效果
2017/11/05 Javascript
Vue调试神器vue-devtools安装方法
2017/12/12 Javascript
在nginx上部署vue项目(history模式)的方法
2017/12/28 Javascript
Vue-CLI3.x 设置反向代理的方法
2018/12/06 Javascript
vue-autoui自匹配webapi的UI控件的实现
2020/03/20 Javascript
PyQt5打开文件对话框QFileDialog实例代码
2018/02/07 Python
python中cPickle类使用方法详解
2018/08/27 Python
Python实现常见的回文字符串算法
2018/11/14 Python
Django集成搜索引擎Elasticserach的方法示例
2019/06/04 Python
Python 中PyQt5 点击主窗口弹出另一个窗口的实现方法
2019/07/04 Python
Python编写memcached启动脚本代码实例
2020/08/14 Python
如何使用Django Admin管理后台导入CSV
2020/11/06 Python
普通简短的个人自我评价
2014/02/15 职场文书
单位未婚证明范本
2014/11/25 职场文书
2014年乡镇安全生产工作总结
2014/12/02 职场文书
一年级语文下册复习计划
2015/01/17 职场文书
收入证明申请书
2015/06/12 职场文书
cf战队宣传语
2015/07/13 职场文书
MySQL 开窗函数
2022/02/15 MySQL