前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

1、Web 与 Node.js 相关技术介绍

1.1、Web应用的基本组件

  web应用的三大部分

  brower(GUI)<==>webserver(business logic、data access)<==>database(data storage)

  GUI(浏览器、HTTP客户端)

  Web服务器(Node.js service)

    请求(浏览器访问网页时发送一个请求给服务器)

    业务逻辑(服务器进行处理请求)

    连接数据库(处理的过程中需要连接数据库,进行数据处理,最后将数据返回给GUI也就是浏览器,这是一个请求响应的过程)

  数据库(SQLite,LevelDB,Redis)

  GET  /yorkie HTTP/1.1

  Host:github.com

  Connection:keep-alive

  Accept:text/html,application/xhtml

  User-Agent:My iPhone

  Accept-Encoding:gzip,deflate,sdch

  (请求的方法(method))get就是个请求请求的方法有很多种,主要有get和post两种,其他还有很多

  /yorkie这部分就是请求的路径,也是一个资源的定位

  1.1这一部分标识使用的HTTP的版本

  Host:github.com这一部分表示我们要访问的域名,访问域名最后就可以转化成一个url了

  

1.2、expressjs框架

  npm install express -g(全局安装成功,不带-g出现错误提示)

  安装成功之后这时桌面(安装完会提示安装到哪了,具体看下图:)会出现node_moudules这么一个文件夹

前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

[lin@vultr ~]$ sudo npm install express -g
/usr/lib
└─┬ express@4.16.
├─┬ accepts@1.3.
│ ├─┬ mime-types@2.1.
│ │ └── mime-db@1.37.
│ └── negotiator@0.6.
├── array-flatten@1.1.
├─┬ body-parser@1.18.
│ ├── bytes@3.0.
│ ├─┬ http-errors@1.6.
│ │ └── inherits@2.0.
│ ├─┬ iconv-lite@0.4.
│ │ └── safer-buffer@2.1.
│ └── raw-body@2.3.
├── content-disposition@0.5.
├── content-type@1.0.
├── cookie@0.3.
├── cookie-signature@1.0.
├─┬ debug@2.6.
│ └── ms@2.0.
├── depd@1.1.
├── encodeurl@1.0.
├── escape-html@1.0.
├── etag@1.8.
├─┬ finalhandler@1.1.
│ └── unpipe@1.0.
├── fresh@0.5.
├── merge-descriptors@1.0.
├── methods@1.1.
├─┬ on-finished@2.3.
│ └── ee-first@1.1.
├── parseurl@1.3.
├── path-to-regexp@0.1.
├─┬ proxy-addr@2.0.
│ ├── forwarded@0.1.
│ └── ipaddr.js@1.8.
├── qs@6.5.
├── range-parser@1.2.
├── safe-buffer@5.1.
├─┬ send@0.16.
│ ├── destroy@1.0.
│ └── mime@1.4.
├── serve-static@1.13.
├── setprototypeof@1.1.
├── statuses@1.4.
├─┬ type-is@1.6.
│ └── media-typer@0.3.
├── utils-merge@1.0.
└── vary@1.1.

在网络服务器上的

  

本地安装:
npm install xxx 安装到命令行所在目录的node_module目录。
全局安装:
npm install xxx -g 安装到 \AppData\Roaming\npm\node_modules目录。

下面一段代码简单实现在浏览器页面显示一部分内容:

var express = require('express');
var app = express(); app.get('/jikexueyuan',function(req,res){
res.send('hello jikexueyuan');
}); app.listen(3000);

以下是在浏览器中显示的内容。  

前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

注意查看expressJS官方API文档的侧边栏的基本组件

2、expressjs 的配置与路由

2.1、expressjs基础

  请求和响应的数据全部放在头部是不现实的。

  get一般是从服务器拿数据,是没有{body}这种东西的

  

//or cristring style

name=hahaha

name=hahaha&foo=bar&x[y]=10
{
name:'hahaha',
foo:'bar',
x: { y: 10}
} //expressjs request_object = {
method:&apos;POST&apos;,
path: &apos;/hahahaha&apos;,
headers:{
&apos;Content-Type&apos;:&apos;application/json&apos;,
...
...
}
body:{}
} request.body = JSON.parse(rawBody);
bodyparser.urlEncoded(); //response HTTP/1.1 200 OK
...
..
... //express
status var response = {}
response.status = function (){};
response.status(200);
response.status(500); response.headers['Content-Type'] = 'application/json';
response.set('Content-Type', 'application/json'); response.send([20]);
response.json()

 

比较重要的点:

  req.path

  req.hostname(主机名)

  req.body

  bodyParser(模组:用处:用来解析BODY的,因为body有很多编码方式(像json、cristring等等)express自己是不会自己进行解析的,bodyParser提供了两种方式

  request.body = JSON.parse(rawBody);

  bodyparser.urlEncoded();

2.2、expressjs的初始化配置

request

|

middleware 1

|

middleware 2

|

middleware 2

|

URL

|

response

  middleware: (中间件----由很多回调函数组成的东西)

    app.use

    app.get

    app.post

  request:

    req.params

    req.query

    req.body

  response:

    res.send()

    next()

2.3、expressjs的路由

2.4、expressjs的返回响应

app = express()

app.use

  body-parser:https://github.com/expressjs/body-parser

res.send()

  plain text

  JSON

代码示例:

var express = require('express');
var app = express(); app.get('/plain-text', function(req, res){
res.status(200).send('<h1>'+"hello"+`world<h1>`);
}); app.get('/category', function(req, res){
res.status(200);
res.json({
python: 20,
nodejs: 1,
others: 10
});
}); var questions = [
{
id:1,
title: 't1',
asker: 'you',
course: 'nodejs',
'last-reply': Date.now(),
reply:1,
state: 'resolved'
},
{
id:2,
title: 't2',
asker: 'you',
course: 'nodejs',
'last-reply': Date.now(),
reply: 1,
state: 'unresolved'
},
{
id:3,
title: 't3',
asker: 'you',
course: 'nodejs',
'last-reply': Date.now(),
reply: 1,
state: 'unresolved'
},
{
id:4,
title: 't4',
asker: 'you',
course: 'nodejs',
'last-reply': Date.now(),
reply: 1,
state: 'unresolved'
}
]; app.get('/questions', function(req, res){
res.status(200);
res.json(questions);
}); //liebiao guolv (jia ru yi ge state) app.get('/questions/all', function(req, res){
res.status(200);
res.json(questions);
}); app.get('/questions/unresolved', function(req, res){
res.status(200);
res.json(questions.filter(function(q){
//console.log("q : "+ q);
//console.log("q.state : " + q.state );
//console.log("q && q.state: " + (q && q.state));
var ppp = q && q.state;
//console.log(ppp);//resolved unresolved unresolved unresolved
//if(q.state === 'unresolved')return q; //This is the same function!!!
if(q.state ==='unresolved')return true;//This is the real function !!!
//return q && q.state === 'unresolved';
}));
}); app.get('/questions/resolved', function(req, res){
res.status(200);
res.json(questions.filter(function(q){
return q && q.state === 'resolved';
}));
}); app.listen(3000);

3、expressjs 与HTML

3.1、使用expressjs返回HTML内容

HTML

  Content-Type:text/html(服务器要返回给客户端什么类型的数据)

  fs.createReadStream('xxx.html').pipe(res)

  res.render()

3.2、模板渲染

模板:

  用途:复用HTML组件,简化开发流程

  比喻:模具

渲染/生成:

  用途:“生成”最终的HTML内容

  比喻:烤饼干

3.3、使用app.set来设置express实例所使用的模板引擎

ejs:http://ejs.co(模板引擎)

使用模板引擎,需要加一个语句(想用其他的模板引擎的话,直接修改ejs这一部分)

app.set('view engine', 'ejs')
res.render('home.ejs', {title: 'ejs template'})

这里出现了cannot find module 'ejs' 的问题,解决办法是在用户目录下执行以下两行命令

npm install ejs -g  (全局安装ejs)(发现全局安装ejs之后并不起作用(这里是我忘了这是普通用户的原因了。)之后再执行下面一行命令)
              (全局安装就是必须用root权限安装,不是root用户就用sudo ,是root就直接使用以上命令安装) npm install ejs  (在代码目录下再安装一次) 安装完成功之后的情况下可以移动当前所在目录的项目了,具体原因未知。不过对我来说,可以用就行了!

render_myprogram2.js

var express = require('express');
var app = express(); app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
/*定义views的路径*/
/*__dirname好像是个全局变量,注意这里是两个下划线*/
app.get('/', function(req, res){
res.render('home.ejs', {name: 'nameishahaha'});
}); app.listen(3000);

home.ejs(views目录下的home.ejs)

<html>
<head>
<title>new template</title>
</head>
<body>
<p> hello hahahahahaha </p>
<p> Hi <%= name %> </p>
</body>
</html>

前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

如何与request对象进行结合:

render_myprogram.js

var express = require('express');
var app = express(); app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
/*定义views的路径*/
/*__dirname好像是个全局变量,注意这里是两个下划线*/
app.get('/', function(req, res){
res.render('home.ejs', {name: 'nameishahaha'});
}); app.get('/request/:id', function(req, res){
var locals = {name: 'gagagagaga', 'id': req.params['id']};
res.render('home.ejs', locals);
}); app.listen(3000);

home.ejs(views目录下的home.ejs)

<html>
<head>
<title>new template</title>
</head>
<body>
<p> hello hahahahahaha </p>
<p> Hi <%= name %> </p>
<p> id <%= id %> </p>
</body>
</html>

前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

3.4、前后端共用模板

在前端渲染(render)模板

<script srv="ejs.js"></script>
ejs.render(tmpl,data)

复制文件ejs.min.js到根目录下的headers文件夹下

这里老师讲的main文件没有引入,不知道原因是什么他运行着没有问题,但是我还是自己引入了main1.js

下面是代码

render_my_program2.js

var express = require('/usr/lib/node_modules/express');
//这里是真的屌,原来这里的参数是express框架的目录,恕我愚钝
//所以这里可以通过在项目目录执行npm install express来解决呢
var app = express(); app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
/*定义views的路径*/
/*__dirname好像是个全局变量,注意这里是两个下划线*/ app.use(express.static(__dirname));
//console.log(__dirname);// /home/lin/lin_nodejs_nodes/my_project1 app.get('/', function(req, res){
res.render('home.ejs', {name: 'nameishahaha'});
}); app.get('/request/:id', function(req, res){
var locals = {name: 'gagagagaga', 'id': req.params['id']};
res.render('home.ejs', locals);
}); app.listen(3000);

/views/home.ejs

<html>
<head>
<title>new template</title>
</head>
<body>
<p> hello hahahahahaha </p>
<p> Hi <%= name %> </p>
<p> id <%= id %> </p>
<input id="new-temp-val" type="text">
<div id="new-temp"></div>
</body> <script type="text/javascript" src="/ejs.min.js"></script>
<!--这里的/ejs.min.js是__dirname/ejs.min.js-->
<script type="text/javascript">
//alert("test_alert"); var tmpl = '<p>A new template</p>';
var newTempDiv = document.getElementById('new-temp'); /* setTimeout(function(){
newTempDiv.innerHTML = ejs.render(tmpl);
},2000);
*/ //因为后面有了main.js所以这里的js代码不管用了,就注释掉可以了
</script>
<script type="text/javascript" src="/main_js_dir/main1.js"></script>
<!--/指的是当前项目的工作路径的根目录,我没写/的时候报错了。-->
</html>

/main_js_dir/main1.js

//alert("test_alert");//alert好像在只有声明了是text/javasceipt类型才会管用,在这里不管用
console.log("????");
var newTemp = document.getElementById('new-temp'); setInterval(function(){
var tmpl = '<p>the value is <%= val1 %></p>';
val1 = document.getElementById('new-temp-val').value || null;
newTemp.innerHTML = ejs.render(tmpl);
},2000);

前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

4、模组化

1、如何设计API

  不要让用户使用关键字new

  保持简洁

  不要轻易地输出接口

2、发布到NPM

  npm publish

  生成一个package.json文件,在生成的时候他会自动地把你的一些内容给输入进去,包括你之前有node modules他会自动识别node modules里面的模组,然后将他们包含在你的package里面,这样你在别人从npm装上你的包的时候就能自动安装这些dependencys(依赖),这样比较方便的,所以npm init是比较方便的东西,等你准备发布之后,你可使用npm publish将你的包上传到npm的服务器上,然后在另外一台机器上你就可以用npm install +你的名字然后就可以将你相应的包下载到对应的node modules目录下

3、课程总结

  express或Node.js在开发Web应用程序的基本流程

  如何在Node.js中复用代码并使用npm来分发

上一篇:java与.net比较学习系列(1) 开发环境和常用调试技巧


下一篇:LightOj 1215 - Finding LCM(求LCM(x, y)=L中的 y )