课堂练习(三)

Simple App

实验目的

  1. 学会使用 Node 编写简单的前端应用。

操作步骤

(1)新建一个目录

$ mkdir simple-app-demo
$ cd simple-app-demo

(2)在该目录下,新建一个package.json文件。

$ npm init -y

package.json是项目的配置文件。

(3)安装jquerywebpack这两个模块。

$ npm install -S jquery
$ npm install -S webpack

打开package.json文件,会发现jquerywebpack都加入了dependencies字段,并且带有版本号。

(4)在项目根目录下,新建一个网页文件index.html

<html>
  <body>
    <h1>Hello World</h1>
    <script src="bundle.js"></script>
  </body>
</html>

(5)在项目根目录下,新建一个脚本文件app.js

const $ = require("jquery");
$("h1").css({ color: "red"});

上面代码中,require方法是 Node 特有的模块加载命令。

(6)打开package.json,在scripts字段里面,添加一行。

"scripts": {
  "build": "webpack app.js bundle.js",
  "test": "...."
},

(7) 在项目根目录下,执行下面的命令,将脚本打包。

$ npm run build

执行完成,可以发现项目根目录下,新生成了一个文件bundle.js

(8)浏览器打开index.html,可以发现Hello World变成了红色。

练习

  1. 修改样式,将标题变为蓝色,然后重新编译生成打包文件。

REST API

实验目的

  1. 熟悉 REST API 的基本用法

操作步骤

(1) 命令行进入rest-api-demo目录,执行下面的命令。

$ npm install -S json-server

(2) 在项目根目录下,新建一个 JSON 文件db.json

{
  "posts": [
    { "id": 1, "title": "json-server", "author": "typicode" }
  ],
  "comments": [
    { "id": 1, "body": "some comment", "postId": 1 }
  ],
  "profile": { "name": "typicode" }
}

(3) 打开package.json,在scripts字段添加一行。

"scripts": {
  "server": "json-server db.json",
  "test": "..."
},

(4) 命令行下执行下面的命令,启动服务。

$ npm run server

(5)打开 Chrome 浏览器的 Postman 应用。依次向http://127.0.0.1:3000/postshttp://127.0.0.1:3000/posts/1发出GET请求,查看结果。

(6)向http://127.0.0.1:3000/comments发出POST请求。注意,数据体Body要选择x-www-form-urlencoded编码,然后依次添加下面两个字段。

body: "hello world"
postId: 1

发出该请求后,再向http://127.0.0.1:3000/comments发出GET请求,查看结果。

(7) 向http://127.0.0.1:3000/comments/2发出PUT请求,数据体Body要选择x-www-form-urlencoded编码,然后添加下面的字段。

body: "hello react"

发出该请求后,再向http://127.0.0.1:3000/comments发出GET请求,查看结果。

(8)向http://127.0.0.1:3000/comments/2发出delete请求。

发出该请求后,再向http://127.0.0.1:3000/comments发出GET请求,查看结果。

Express

实验目的

  1. 学会 Express 搭建 Web 应用的基本用法。

操作步骤

(1)进入demos/express-demo目录,命令行执行下面的命令,安装依赖。

$ cd demos/express-demo
$ npm install

(2)打开app1.js,尝试看懂这个脚本。

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

上面代码调用express,生成一个 Web 应用的实例。

var router = express.Router();

router.get("/", function(req, res) {
  res.send("<h1>Hello World</h1>");
});

app.use("/home", router);

上面代码新建了一个路由对象,该对象指定访问根路由(/)时,返回Hello World。然后,将该路由加载在/home路径,也就是说,访问/home会返回Hello World

router.get方法的第二个参数是一个回调函数,当符合指定路由的请求进来,会被这个函数处理。该函数的两个参数,reqres都是Express 内置的对象,分别表示用户的请求和 Web 服务器的回应。res.send方法就表示服务器回应所送出的内容。

var port = process.env.PORT || 8080;

app.listen(port);
console.log("Magic happens on port " + port);

上面代码指定了外部访问的端口,如果环境变量没有指定,则端口默认为8080。最后两行是启动应用,并输出一行提示文字。

(3)在命令行下,启动这个应用。

$ node app1.js

浏览器访问localhost:8080/home,看看是否输出Hello World

然后,命令行下按 Ctrl + C,退出这个进程。

(4)通过环境变量,自定义启动端口。

假定我们指定必须启动在7070端口,命令行可以这样操作。

# Linux & Mac
$ PORT=7070 node app1.js

# windows
$ set PORT=7070
$ node app1.js

浏览器就可以访问localhost:7070/home了。

然后,命令行下按 Ctrl + C,退出这个进程。

思考题:Node 应用能否直接在80端口启动?

(5)打开app2.js,查看新增的那个路由。

router.get("/:name", function(req, res) {
  res.send("<h1>Hello " + req.params.name + "</h1>");
});

上面代码新增了一个路由,这个路由的路径是一个命名参数:name,可以从req.params.name拿到这个传入的参数。

在命令行下,启动这个应用。

$ node app2.js

浏览器访问localhost:8080/home/张三,看看是否输出Hello 张三

然后,命令行下按 Ctrl + C,退出这个进程。

(6)打开app3.js,先查看页面头部新增的两行代码。

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

// 新增代码...
var bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));

// ...

上面代码中,body-parser模块的作用,是对POSTPUTDELETE等 HTTP 方法的数据体进行解析。app.use用来将这个模块加载到当前应用。有了这两句,就可以处理POSTPUTDELETE等请求了。

下面查看新增的那个路由。

router.post("/", function (req, res) {
  var name = req.body.name;
  res.json({message: "Hello " + name});
});

上面代码表示,如果收到了/路径(实际上是/home路径)的POST请求,先从数据体拿到name字段,然后返回一段 JSON 信息。

在命令行下,启动这个应用。

$ node app3.js

然后,在 Chrome 浏览器的 Postman 插件里面,向http://127.0.0.1:8080/home发出一个POST请求。数据体的编码方法设为x-www-form-urlencoded,里面设置一个name字段,值可以随便取,假定设为Alice。也就是说,发出这样一个请求。

POST /home HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded

name=Alice

如果一切正常,服务器会返回一段 JSON 信息。

{
  "message": "Hello Alice"
}

(7)打开app4.js,查看在所有路由之前新增的那个函数。

var router = express.Router();

// 新增的代码
router.use(function(req, res, next) {
  console.log("Thers is a requesting.");
  next();
});

router.get("/", function(req, res) {
  // ...

router.use的作用是加载一个函数。这个函数被称为中间件,作用是在请求被路由匹配之前,先进行一些处理。上面这个中间件起到 logging 的作用,每收到一个请求,就在命令行输出一条记录。请特别注意,这个函数内部的next(),它代表下一个中间件,表示将处理过的请求传递给下一个中间件。这个例子只有一个中间件,就进入路由匹配处理(实际上,bodyparserrouter本质都是中间件,整个 Express 的设计哲学就是不断对 HTTP 请求加工,然后返回一个 HTTP 回应)。

练习

  1. 请增加一个中间件,服务器每次收到用户请求,会在服务器的控制台打印出收到请求的时间。

  2. URL 的查询字符串,比如localhost:8080?name=Alice里面的name,可以用req.query.name拿到。请修改一个路由,使之可以收到查询字符串,然后输出"Hello " + req.query.name

文章导航