Node.js进行Web开发(一)--Express,路由控制,模板引擎

         1.1、Node.js 和 PHP、Perl 、ASP 、JSP  一样,目的都是实现动态网页,也就是说由服务器动态生成 HTML  页面。之所以要这么做,是因为静态 HTML  的可扩展性非常有限,无法与用户有效交互。同时如果有大量相似的内容,例如产品介绍页面,那么1000个产品就要1000个静态的 HTML 页面,维护这1000个页面简直是一场灾难,因此动态生成 HTML  页面的技术应运而生。

         Node.js本质上和 Perl 或 C++ 一样,都可以作为 CGI 扩展被调用,但它还可以跳过 HTTP 服务器,因为它本身就是。传统的架构中 HTTP  服务器的角色会由Apache 、Nginx、IIS  之类的软件来担任,而Node.js  不需要②。Node.js 提供了 http 模块,它是由C++  实现的,性能可靠,可以直接应用到生产环境。下图是一个简单的架构示意图。

Node.js 和其他的语言相比的另一个显著区别,在于它的原始封装程度较低。例如 PHP 中

你可以访问  $_REQUEST  获取客户端的 POST  或 GET  请求,通常不需要直接处理 HTTP 协议。这些语言要求由HTTP 服务器来调用,因此你需要设置一个 HTTP 服务器来处理客户端的请求,HTTP  服务器通过CGI  或其他方式调用脚本语言解释器,将运行的结果传递回 HTTP 服务器,最终再把内容返回给客户端。而在 Node.js  中,很多工作需要你自己来做(并不是都要自己动手,因为有第三方框架的帮助)。

1.2、  Express 框架

npm 提供了大量的第三方模块,其中不乏许多 Web   框架,我们没有必要重复发明轮子,

因而选择使用 Express 作为开发框架,因为它是目前最稳定、使用最广泛,而且 Node.js 官方推荐的唯一一个 We b   开发框架。 Express ( http://expressjs.com/  )  除了为 http  模块提供了更高层的接口外,还实现了许多功能,其中包括:

   路由控制;

   模板解析支持;

   动态视图;

   用户会话;

   CSRF  保护;

   静态文件服务;

   错误控制器;

   访问日志;

   缓存;

   插件支持。

需要指出的是,Express 不是一个无所不包的全能框架,像 Rails  或 Django  那样实现了

模板引擎甚至 ORM  (Object Relation Model,对象关系模型)。它只是一个轻量级的 Web   框架,多数功能只是对 HTTP  协议中常用操作的封装,更多的功能需要插件或者整合其他模块来完成。

 

1.3、 安装 Express

首先我们要安装 Express 。如果一个包是某个工程依赖,那么我们需要在工程的目录下使用本地模式安装这个包,如果要通过命令行调用这个包中的命令,则需要用全局模式安装,因此按理说我们使用本地模式安装 Express 即可。但是Express 像很多框架一样都提供了 Quick Start(快速开始)工具,这个工具的功能通常是建立一个网站最小的基础框架,在此基础上完成开发。当然你可以完全自己动手,但我还是推荐使用这个工具更快速地建立网站。为了使用这个工具,我们需要用全局模式安装 Express,因为只有这样我们才能在命令行中使用它。运行以下命令:

$ npm install -g express

等待数秒后安装完成,我们就可以在命令行下通过 express 命令快速创建一个项目了。

在这之前先使用 express --help 查看帮助信息:

Usage: express [options][path]

 Options:

  -s, --sessions           add session support

  -t, --template   add template support(jade|ejs). default=jade -c, --css        add stylesheet support(stylus). default=plain css

  -v, --version          output framework version

  -h, --help             output help information

Express 在初始化一个项目的时候需要指定模板引擎,默认支持Jade 和ejs,为了降低学

习难度我们推荐使用 ejs ,同时暂时不添加 CSS  引擎和会话支持。




1.4、建立工程

通过以下命令建立网站基本结构:

express -e blog

当前目录下出现了子目录blog ,并且产生了一些文件:

它还提示我们要进入其中运行 npm install,我们依照指示,结果如下:

它自动安装了依赖 ejs  和 express。这是为什么呢?检查目录中的 package.json 文件,内容是:


{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.4.7",
    "ejs": "*"
  }
}

1.5、  启动服务器

用 Express 实现的网站实际上就是一个 Node.js 程序,因此可以直接运行。我们运行 node app.js,看到  Expressserver listening on  port 3000 indevelopment mode。

接下来,打开浏览器,输入地址 http://localhost:3000,你就可以看到一个简单的 Welco me 

to Express  页面了。如果你能看到如图所示的页面,那么说明你的设定正确无误。


1.6、工程的结构、现在让我们回过头来看看 Express 都生成了哪些文件。除了 package.json ,它只产生了两

个 JavaScript 文件 app.js  和 routes/index.js。模板引擎 ejs  也有两个文件 index.ejs 和layout.ejs ,此外还有样式表 style.css 。下面来详细看看这几个文件。


app.js:启动文件,或者说入口文件
package.json
:存储着工程的信息及模块依赖,当在 dependencies中添加依赖的模块时,运行 npm installnpm会检查当前目录下的 package.json,并自动安装所有指定的模块
node_modules
:存放 package.json中安装的模块,当你在 package.json添加依赖的模块并安装后,存放在这个文件夹下
public
:存放 imagecssjs等文件
routes
:存放路由文件
views
:存放视图文件或者说模版文件

1. app.js 

app.js  是工程的入口,我们先看看其中有什么内容:


/**
 * Module dependencies.
 */

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

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
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'));
});

Express 依赖于 connect,提供了大量的中间件,可以通过 app.use 启用。app.configure

中启用了5个中间件:bodyParser 、methodOverride 、router、static 以及 errorHandler 。

bodyParser  的功能是解析客户端请求,通常是通过 POST  发送的内容。methodOverride

用于支持定制的 HTTP  方法。router 是项目的路由支持。static 提供了静态文件支持。

errorHandler  是错误控制器。

 app.get('/', routes.index); 是一个路由控制器,用户如果访问“ /  ”路径,则由routes.index 来控制。 最后服务器通过 app.listen(3000);  启动,监听3000端口。


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

这段代码的意思是创建 http 服务器并监听 3000 端口,成功后在命令行中显示   Express serverlistening on port 3000 ,然后我们就可以在浏览器访问 localhost:3000 了。

 2. routes/index.js

routes/index.js 是路由文件,相当于控制器,用于组织展示的内容:

/*
 * GET home page.
 */

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

app.js  中通过 app.get('/', routes.index);  将“ /  ”路径映射到 exports.index 函数下。其中只有一个语句 res.render('index', { title: 'Express' }),功能是调用模板解析引擎,翻译名为 index  的模板,并传入一个对象作为参数,这个对象只有一个属性,即  title:'Express'。

 

3. index.ejs

index.ejs  是模板文件,即 routes/index.js 中调用的模板,内容是:



  
    <%= title %>
    
  
  
    

<%= title %>

Welcome to <%= title %>


它的基础是 HTML  语言,其中包含了形如  <%=title %> 的标签,功能是显示引用的变量,即 res.render   函数第二个参数传入的对象的属性。

 

现在我们学习了如何创建一个工程并启动它,了解了工程的大体结构,下面我们将学习 express的基本使用及路由控制。

 

2、 路由控制

 

2.1  工作原理

当通过浏览器访问 app.js 建立的服务器时,会看到一个简单的页面,实际上它已经完成了许多透明的工作,现在就让我们来解释一下它的工作机制,以帮助理解网站的整体架构。

前面提到过 app.js app.get('/', routes.index) 可以用以下代码取代:

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

这段代码的意思是当访问主页时,调用ejs模板引擎,来渲染 index.ejs模版文件(即将 title变量全部替换为字符串 Express),生成静态页面并显示在浏览器中。我们来作一些修改,以上代码实现了路由的功能,我们当然可以不要 routes/index.js文件,把实现路由功能的代码都放在app.js里,但随着时间的推移 app.js会变得臃肿难以维护,这也违背了代码模块化的思想,所以我们把实现路由功能的代码都放在 routes/index.js里。官方给出的写法是在 app.js中实现了简单的路由分配,然后再去 index.js中找到对应的路由函数,最终实现路由功能。我们不妨把路由控制器和实现路由功能的函数都放到 index.js里,app.js 中只有一个总的路由接口。

打开 app.js,删除:

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

注意:目前我们用不到 routes/user.js,也可以删除这个文件,同时删除 app.js var user = require('./routes/user');

app.js最后添加一行代码:

routes(app);

修改 index.js如下:

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

现在,再运行你的 app,你会发现主页毫无二致。这里我们在 routes/index.js中通过 module.exports 导出了一个函数接口,在 app.js 中通过 require 加载了 index.js 然后通过 routes(app) 调用了 index.js 导出的函数。

Express 创建的网站架构如下:



这是一个典型的 MVC 架构,浏览器发起请求,由路由控制器接受,根据不同的路径定向到不同的控制器。控制器处理用户的具体请求,可能会访问数据库中的对象,即模型部分。控制器还要访问模板引擎,生成视图的 HTML,最后再由控制器返回给浏览器,完成一次请求。

express封装了多种 http 请求方式,我们主要只使用 get  post 两种,即 app.get()  app.post() app.get()  app.post() 的第一个参数都为请求的路径,第二个参数为处理请求的回调函数,回调函数有两个参数分别是 req res,代表请求信息和响应信息

2.2 、创建路由规则

当我们在浏览器中访问譬如 http://localhost:3000/abc  这样不存在的页面时,服务器会在

响应头中返回 404 Not Found 错误,


这是因为 /abc 是一个不存在的路由规则,而且它也不是一个 public  目录下的文件,所以Express返回了404 Not Found的错误。

接下来我们会讲述如何创建路由规则。 假设我们要创建一个地址为 /hello 的页面,内容是当前的服务器时间,让我们看看具体做法。打开 app.js ,在已有的路由规则  app.get('/', routes.index) 后面添加一行:

app.get('/hello',routes.hello);

修改 routes/index.js,增加 hello函数:

/* 
 * GET home page. 
 */ 
 exports.index = function(req, res) { 
  res.render('index', { title: 'Express' }); 
exports.hello = function(req, res) { 
  res.send('The time is ' + new Date().toString()); 
}; 

重启 app.js ,在浏览器中访问 http://localhost:3000/hello ,可以看到类似于下图的页面,


刷新页面可以看到时间发生变化,因为你看到的内容是动态生成的结果。

 服务器在开始监听之前,设置好了所有的路由规则,当请求到达时直接分配到响应函数。app.get  是路由规则创建函数,它接受两个参数,第一个参数是请求的路径,第二个参数是一个回调函数,该路由规则被触发时调用回调函数,其参数表传递两个参数,分别是 req  和  res ,表示请求信息和响应信息。

很简单吧?我们学习了基本的路由规则及如何添加一条路由规则,马上我们将学习模板引擎的知识。

3.1、  模板引擎

在这里,我们会讲述模板引擎的使用和集成,也就是视图。视图决定了用户最终能看到什么,因此也是最重要部分,这里我们以 ejs  为例介绍模板引擎的使用方法。

模板引擎的功能是将页面模板和要显示的数据结合起来生成 HTML  页面。它既可以运

行在服务器端又可以运行在客户端,大多数时候它都在服务器端直接被解析为 HTML,解析完成后再传输给客户端,因此客户端甚至无法判断页面是否是模板引擎生成的。有时候模板引擎也可以运行在客户端,即浏览器中,典型的代表就是 XSLT ,它以 XML  为输入,在客户端生成 HTML 页面。但是由于浏览器兼容性问题,XSLT 并不是很流行。目前的主流还是由服务器运行模板引擎。

3.2、  使用模板引擎

基于 JavaScript  的模板引擎有许多种实现,我们推荐使用 ejs  (Embedded JavaScript ),

因为它十分简单,而且与 Express  集成良好。由于它是标准 JavaScript  实现的,因此它不仅可以运行在服务器端,还可以运行在浏览器中。我们这一章的示例是在服务器端运行 ejs ,

这样减少了对浏览器的依赖,而且更符合传统架构的习惯。

我们在 app.js  中通过以下两个语句设置了模板引擎和页面模板的位置:

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

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

表明要使用的模板引擎是 ejs ,页面模板在 views 子目录下。在 routes/index.js  的

exports.index 函数中通过如下语句调用模板引擎:

res.render('index', { title:'Express' });

res.render  的功能是调用模板引擎,并将其产生的页面直接返回给客户端。它接受

两个参数,第一个是模板的名称,即 views  目录下的模板文件名,不包含文件的扩展名;第二个参数是传递给模板的数据,用于模板翻译。index.ejs  内容如下:



  
    <%= title %>
    
  
  
    

<%= title %>

Welcome to <%= title %>


上面代码其中有两处 <%= title %> ,用于模板变量显示,它们在模板翻译时会被替换成 Express ,因为 res.render  传递了 { title: 'Express' }。

ejs 的标签系统非常简单,它只有以下3种标签。

   <% code %>:JavaScript  代码。

   <%= code %> :显示替换过 HTML  特殊字符的内容。

   <%- code %> :显示原始 HTML  内容。

我们可以用它们实现页面模板系统能实现的任何内容。

渲染后生成的页面代码为:



  
    Express
    
  
  
    

Express

Welcome to Express




你可能感兴趣的:(node.js)