[笔记]web前端开发之Node.js(2):Node.js和express构建网站

本文由清尘发表于2021-05-26 13:21最后修改于2021-06-01属于javascript分类

相关链接:
[笔记]web前端开发之Node.js(1):与mysql的交互
[笔记]web前端开发之Node.js(2):Node.js和express构建网站
[笔记]web前端开发之Node.js(3):Node.js和Express实现上传文件功能

Express是一个轻量级、简洁、易用的Node.js Web MVC开发框架,它基于Node.js原有进行了很多Web开发所需的功能封装
http://expressjs.com/
https://www.npmjs.com/package/express

安装
-g表示全局安装

npm install -g express-generator

创建一个testWebApp

express testWebApp

安装依赖项:注意上一步安装成功后的提示,需要cd到网站目录,并执行npm install 命令安装项目依赖项(可以在项目的package.json文件的dependencies节点下看到需要哪些依赖)

默认启动后是3000端口 http://127.0.0.1:3000/

修改 app.js文件并运行
在testWebApp根目录下找到app.js并增加端口监听
启动,并查看运行效果

...
var app = express();
app.listen(8100,function(){
  console.log("Server Start:http://127.0.0.1:8100/");
})
...

在上面创建的testWebApp中express默认使用的模版引擎为jade,jade虽然简洁但不直观,所以选择了更易上手的ejs.这也是现在运用最为广泛的nodejs模板之一。
创建一个Node.js基于ejs的项目

express -e testEjsWebApp
cd testEjsWebApp
npm install

创建成功后打开routes文件夹下的index.js 修改部分代码

...
  res.render("index", {
    title: "<h1>Express</h1>",
    users: [
      { username: "wilson" },
      { username: "zhong" },
      { username: "wei hong" },
    ],
  });
...

打开views,修改部分代码

    <%- title %>
    <%= title %>
    <hr>
    <% users.forEach(function(user){ %>
      <h4><%- user.username %></h4>
    <%}) %>

ejs结尾的文件就是模板文件,可以看到在文件中我们用了两种标签方式(这种标签方式有过其它web开发经验的应该很好看懂)

1.

 
<%= %>

这个标签在接收到title时,从显示效果来看,他直接输出HTML标签在页面上,输出的是转义后的变量值

2.

<% %>

这个标签,从显示上看,他循环了出来参数中的值,标签中是javascript逻辑代码,注意括号的开闭合。

app.js

app.set(name,value):把名字为name的项的值设为value,用于设置参数

app.use([path],function):用这个方法来使用中间件,因为express依赖于connect,有大量的中间件,可以通过app.use来使用;path参数可以不填,默认为’/’

app.get(name):获取名为name的项的值

router.get表示通过get请求/时,响应后面的function处理,两个参数分别是request、response; res.render表示调用模板引擎解析名字index的模板,传入了title和users两个对象做为参数。

======

以下内容完整代码演示:

https://github.com/shine130/EjsPre2
https://git.code.tencent.com/devpro/EjsPre2

修改app.js引入新创建的路由

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var subform = require('./routes/subform');
var usesession = require("./routes/usesession");
var usecookies = require("./routes/usecookies");
var usecrypto = require("./routes/usecrypto");


var app = express();
app.listen(8000,function(){
  console.log("Server Start:http://127.0.0.1:8000/");
});

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use("/subform", subform);
app.use("/usesession", usesession);
app.use("/usecookies", usecookies);
app.use("/usecrypto", usecrypto);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

如何提取页面公共部分
每个页面都有相同的代码则可以提取出来做公共页面处理
1.在view目录下新建一个nav.ejs文件,导航部分
2.把view目录的4个页面都修改成导入公共页面代码 区别于express2.0

<%include 文件名%>

如何提交表单并接受参数

  <!-- action默认当前页,method默认get -->
  <form method="post">
    用户名:<input type="text" id="txtUserName" name="txtUserName" />
    密码:<input type="password" id="txtUserPwd" name="txtUserPwd" />
    <input type="submit" value="提交">
  </form>

接收数据

var express = require('express');
var router = express.Router();

/* GET home page */
router.get('/',function(req,res){
  var userName = req.query.txtUserName,
    userPwd = req.query.txtUserPwd,
    userName2 = req.param("txtUserName"),
    userPwd2 = req.param("txtUserPwd");

    console.log('req.query用户名:' + userName);
    console.log('req.query密码:' + userPwd);
    console.log("req.param用户名:" + userName2);
    console.log("req.param密码:" + userPwd2);


  res.render('subform',{title:"提交表单及接受参数示例"})
})

router.post("/", function (req, res) {
  var userName = req.body.txtUserName,
    userPwd = req.body.txtUserPwd,
    userName2 = req.param("txtUserName"),
    userPwd2 = req.param("txtUserPwd");

  console.log("req.query用户名:" + userName);
  console.log("req.query密码:" + userPwd);
  console.log("req.param用户名:" + userName2);
  console.log("req.param密码:" + userPwd2);

  res.render("subform", { title: "提交表单及接受参数示例" });
});

module.exports = router;

如何对字符串加密

表单提交后的数据需要加密

//生成口令的散列值
var md5 = crypto.createHash('md5'); //crypto模块功能是加密并生成各种散列
var en_upwd = md5.update(userPwd).digest('hex');

Node.js提供的加密模块功能非常强大,Hash算法就提供了MD5、sha1、sha256等,根据需要去使用
Update方法
digest([encoding])方法,计算数据的hash摘要值

var express = require('express');
var crypto = require('crypto');
var router = express.Router();

/* GET home page */
.....

router.post("/", function (req, res) {
  var userName = req.body.txtUserName,
    userPwd = req.body.txtUserPwd,
    userName2 = req.param("txtUserName"),
    userPwd2 = req.param("txtUserPwd");

  // 对pwd进行加密
  var md5 = crypto.createHash("md5");
  var en_upwd = md5.update(userPwd).digest("hex");

  console.log("req.query用户名:" + userName);
  console.log("req.query密码:" + en_upwd);
  console.log("req.param用户名:" + userName2);
  console.log("req.param密码:" + userPwd2);

  res.render("subform", { title: "提交表单及接受参数示例" });
});

module.exports = router;

如何使用Session

了解Internet通讯协议分为stateful和stateless两类
Node.js中的Session用法
通过npm安装这个中间件
打开app.js进行修改(注意最新版本有改动)
修改js和ejs

安装

npm install express-session --save

修改app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
...
var session = require('express-session');

var app = express();
...
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser("shine"));
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
  secret:'shine',
  resave:true,
  saveUninitialized:false
}))

app.use('/', indexRouter);
...

使用session,修改usession.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
  <%include nav%>

  <%if(locals.islogin){%>
    用户已经登录
  <%}else{%>
    <form method="post">
      <input type="submit" value="登录">
    </form>
  <%}%>

  </body>
</html>

修改路由usesession.js

var express = require("express");
var router = express.Router();


router.get("/", function (req, res) {
  if(req.session.islogin){
    console.log("usesession:" + req.session.islogin);
    res.locals.islogin = req.session.islogin;
  }


  res.render("usesession", { title: "使用sesession示例" });
});


router.post("/", function (req, res) {
  req.session.islogin = 'success';
  res.locals.islogin = req.session.islogin;

  res.render("usesession", { title: "使用sesession示例" });
});

module.exports = router;

如何使用cookies
和session思路一样,在useCookies部分登录同时记录。自动登录
如何清除session和cookies

  res.clearCookie("isLogin"); //清除cookies
  req.session.destroy(); //清除session
var express = require("express");
var router = express.Router();

router.get("/", function (req, res) {
  if (req.session.islogin) {
    console.log("usecookies:" + req.session.islogin);
    res.locals.islogin = req.session.islogin;
  }

  res.render("usecookies", { title: "提交cookies示例" });
});

router.post("/", function (req, res) {
  req.session.islogin = "success";
  res.locals.islogin = req.session.islogin;

  res.cookie('islogin','sucess',{maxAge:60000})

  res.render("usecookies", { title: "使用cookies示例" });
});

module.exports = router;

完整项目代码在dev分支 :
https://git.code.tencent.com/devpro/EjsPre2/tree/dev
https://github.com/shine130/EjsPre2/tree/dev