前端(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这么一个文件夹

[lin@vultr ~]$ sudo npm install express -g
/usr/lib
└─┬ express@4.16.4 
  ├─┬ accepts@1.3.5 
  │ ├─┬ mime-types@2.1.21 
  │ │ └── mime-db@1.37.0 
  │ └── negotiator@0.6.1 
  ├── array-flatten@1.1.1 
  ├─┬ body-parser@1.18.3 
  │ ├── bytes@3.0.0 
  │ ├─┬ http-errors@1.6.3 
  │ │ └── inherits@2.0.3 
  │ ├─┬ iconv-lite@0.4.23 
  │ │ └── safer-buffer@2.1.2 
  │ └── raw-body@2.3.3 
  ├── content-disposition@0.5.2 
  ├── content-type@1.0.4 
  ├── cookie@0.3.1 
  ├── cookie-signature@1.0.6 
  ├─┬ debug@2.6.9 
  │ └── ms@2.0.0 
  ├── depd@1.1.2 
  ├── encodeurl@1.0.2 
  ├── escape-html@1.0.3 
  ├── etag@1.8.1 
  ├─┬ finalhandler@1.1.1 
  │ └── unpipe@1.0.0 
  ├── fresh@0.5.2 
  ├── merge-descriptors@1.0.1 
  ├── methods@1.1.2 
  ├─┬ on-finished@2.3.0 
  │ └── ee-first@1.1.1 
  ├── parseurl@1.3.2 
  ├── path-to-regexp@0.1.7 
  ├─┬ proxy-addr@2.0.4 
  │ ├── forwarded@0.1.2 
  │ └── ipaddr.js@1.8.0 
  ├── qs@6.5.2 
  ├── range-parser@1.2.0 
  ├── safe-buffer@5.1.2 
  ├─┬ send@0.16.2 
  │ ├── destroy@1.0.4 
  │ └── mime@1.4.1 
  ├── serve-static@1.13.2 
  ├── setprototypeof@1.1.0 
  ├── statuses@1.4.0 
  ├─┬ type-is@1.6.16 
  │ └── media-typer@0.3.0 
  ├── utils-merge@1.0.1 
  └── vary@1.1.2 
在网络服务器上的

  

本地安装:
npm install xxx 安装到命令行所在目录的node_module目录。
全局安装:
npm install xxx -g 安装到 AppDataRoaming pm ode_modules目录。

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

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

app.get('/jikexueyuan',function(req,res){
  res.send('hello jikexueyuan');
});

app.listen(3000);

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

注意查看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>

 如何与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>

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);

 

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来分发

原文地址:https://www.cnblogs.com/foreverlin/p/10135236.html