Node.js是什么?

官方概念:Node.js® 是一个基于 Chrome V8 引擎 的 JavaScript 运行时
个人理解:
1.是一个运行环境,可以来跑js.也可以使前端完成一些后端做的事情 比如 可以自己写api(接口)、读写数据库等等.
Tip:Node.js知识一个环境,不是一个编程语言.其中,比较重要的是模块系统(能用不同的模块来完成不同的功能)、npm包管理工具(管理我们的需要的第三方包).

Node.js下载
下载就不多说了,官网自行下载哈.
版本号一定要和后端的hxd相同,不要让自己裂开好吗!!!!

Node.js与浏览器端的区别

  1. 浏览器端:(1)js由ECMAScript+BOM+DOM
  2. 在Node.js端:(1)有ECMAScript+内置模块.Tip:node.js中没有BOM、DOM、Window,但是使用ECMAScript时通用的.
  3. 相同点:(1)都可以运行js代码 (2)都要下载才能使用
  4. 不同点:(1)api不同 node没有BOM、DOM、Window.(2)node可以去实现一些后端的功能(3)浏览器环境可实现前端功能

小黑窗(小蓝窗)
方法1:最简单的:win+r 输入cmd
2022-04-25T09:37:26.png
方法2:在资源管理器地址连 直接输入cmd
方法3:小蓝窗(powershell) 在你想打开小蓝窗的位置,按住shift和鼠标右键 就可以看到powershell的选项了.

常见命令行工具
学过linux的可以跳过此处了,哈哈哈.
有这些命令吊打二流高手没有一点问题!

 1. clear/cls-----清空当前页面
 2. ls/dir-------查看列表
 3. cd .. -------返回上一级目录
 4. cd \  ---------直接回到根目录
 5. ctrl+c ------停止运行当前命令(停止Node程序)
 6. node 空格  xxxx.js   ----调用node程序,运行xxxx.js 这个js文件.
 7. history   ---- 查看历史指令(在当前窗口的操作记录)
 8. Tab键   -------补全文件名或目录名(linux里面最好的,配置ip地址时没有他会头疼死)
 9. ↑↓上下方向键 ------切换历史输入
 10. cv -----这里只能用鼠标右键

模块

模块分类:
1.核心模块(内置模块)
2.自定义模块(类似自定义函数)
3.第三方模块(类似 js被人封装的第三方库如 axios.js day.js)

fs模块

fs模块(fs是 FileSystem的简写)是Node.js用来进行文件操作的模块,它属于核心模块。
引入就可以直接使用

const fs=require('fs') 

使用方法:

fs.各种API(实参)
官方文档:http://nodejs.cn/api/fs.html (尤大名言:看文档!)

fs-readFileSync-文件读取

2022-04-25T10:55:42.png
fs.readFileSync(path[, options])
功能:返回 path 的内容。

const fs = require("fs")
let fs = fs.readFileSync('文件路径',"utf8")
// fs 就是读出来的内容
console.log(rs)

tip:api的名字结尾有Sync(async是异步的,sync表示同步的)

与js相同,读取成功,则会获取读出来的数据,如果读取失败,则会中断后面所有代码的执行.
console.log(1)
let res = fs.readFileSync('errorPath.js')
console.log(res)
console.log(2) // 这句代码是不会执行的

解决方案 :try catch

try {
可能会有错误的代码
} catch(err){
如果try内的代码有错误,就会进入catch,并把错误传进来
}

fs-writeFileSync-文件写入

功能:向指定文件中写入字符串, 如果没有该文件则尝试创建该文件。

fs.writeFileSync(pathName, content, option);
参数1: 要写入的文件路径 --- 相对路径和绝对路径均可,推荐使用绝对路径
参数2: 要写入文件的内容
参数3: 配置项,设置写入的字符集,默认utf-8

注意:它是覆盖写入,会把文件中的内容全部删除,再填入新的内容。

__dirname __filename 获取绝对路径

nodejs中提供了两个全局变量来获取获取绝对路径:

● __filename:获取当前被执行的文件的绝对路径
● __dirname:获取当前被执行的文件的文件夹所处的绝对路径

全局变量的含义是:

● 变量:它们的值是变化的。在不同的文件中值就不同,因为文件的路径也不同嘛。
● 全局:在任意地方都可以直接使用。

只需要在读入文件时,在文件名的前面拼接上路径:

1) 找到当前文件夹的绝对路径
console.log(__dirname)
2) 加上 html5.jpg
const fs = require('fs')
const filePath = __dirname + '\\rs.txt'
console.log(filePath)
const rs = fs.readFileSync(filePath)

path模块

官方文档:http://nodejs.cn/api/path.html (尤大名言:看文档!)
引入模块

const path = require('path')

相关api

path.basename() :此方法返回 path 的最后一部分。一般可用来获取路径中的文件名
path.join() :路径拼接。
path.parse(pathurl) :把一个路径转成一个对象

模块化

在之前写项目的时候,我们调用两个js文件中的函数都是先将两个js文件到index.html
比如
根目录
├── index.html # 主页的页面
├── index.js # 主页需要用到的js代码
│   └── getData() # 是index.js中定义的函数
└── tool.js # 为整个项目提供公共方法
   └── doSomething(){ } # 是tool.js中定义的函数
(此处举例其他页面同)
这样操作很麻烦昂,为什么不能更直接再index.js里面去调用tool.js里卖弄的函数呢?
原因是再蛮早之前,ES5中是不支持模块化的,也就是说不能再一个js文件中去调用另一个js文件的方法,必须要用第三个文件来引入.

什么是模块化

那什么是模块化呢:

一个js文件可以引入其他的js文件,能够使用引入的js文件中的变量、数据,这种特性就称之为模块化.
使用模块化开发,可以很好的解决变量、函数名称冲突的问题,也能灵活地解决文件依赖的问题.

模块化的发展

以前

  1. es5不支持模块化,让前端人员很为难.为了让支持模块化,我们一般都会借用第三方库来自实现:
    sea.js. https://www.zhangxinxu.com/sp/seajs/
    require.js. https://requirejs.org/

现在

  1. es6原生语法也支持模块化(这里并不是表示浏览器也直接支持模块化---需要单独设置一下)

Nodejs内部也支持模块化(与es6模块化有些不同之处)

常见的模块化规范

    1. CommonJS 规范(nodejs 默认支持的)
    1. ES6 模块化规范
    1. CMD 和 AMD 模块化规范(不再推荐使用)[sea.js与require.js]

Node.js中CommonJs的模块化规范

Commonjs规范

    1. 导入其它模块时,统一使用 require() 函数。
    1. 每个 .js 文件,都是一个独立的模块,模块内的成员都是私有的
    1. 在每个 JS 模块中,使用 module.exports 向外共享成员。
      2022-04-26T13:07:48.png
      注意

      • module.exports 是固定写法,一般放在文件的最末尾,也只用一次。
      • module.exports表示当前模块要暴露给其它模块的功能
      • 它可以导出对象,数组,函数等等类型。为了方便组织代码,导出对象的情况比较多。
      • 不必要导出所有函数,对象,数组等。那些没有导出的部分就相当于这个模块的内部变量了。在下图中变量1,函数1,数组就是模块内部的数据,在外部无法别访问到。

总结

  • 所谓定义模块,就是新建一个js文件。文件取名时,要注意一下:
  • 一般会用模块名给它命名。类比于核心模块,例如,你的模块叫myModule,则这个js文件最好叫myModule.js
  • 不要与核心模块的名字重复了。就像我们定义变量不要与核心关键字重名,你自己定义的模块也不要叫fs.js,因为nodejs有一个核心模块就叫fs.js。
  • 要记得导出模块

导出模块有两种方式

  • exports
  • module.exports

    const myPI = 3.14
    const add = (a,b) => a + b;
    // 方法一:
    exports.myPI = myPI
    exports.add = add
    module.exports.myPI = myPI
    module.exports.add = add
      // 方法二(变形)
      module.exports  = {
      myPI,
      add }
    

两个对象的关系

初始exports和module.exports是指向同一块内存区域,其内容都是一个空对象。(exports是module.exports的别名)即:

exports === module.exports // 输出是 true

所以下面两种写法的效果是一样的:

// 写法1 mymodule.js
 exports.f = function(){ }
 exports.pi = 3.1415926 

 // 写法2 mymodule.js
 module.exports.f = function(){ }
 module.exports.pi = 3.1415926
  • 在定义模块时:

如果直接给exports对象赋值(例如:exports={a:1,b:2}),此时,exports就不会再指向module.exports,而转而指向这个新对象,此时,exports与module.exports不是同一个对象。

在引入某模块时:以该模块代码中module.exports指向的内容为准。
要注意module.exports和exports中值类型和引用类型的问题!!!!
另外这两个方法,并不能一起运用。因为使用module.exports赋值就相当于使其指向新的对象。之前的exports赋值都会失效。

npm

Snipaste_2022-04-26_16-10-31.png

下载包-修改镜像源
下包速度慢的原因:默认情况下,npm 从一个名为 https://registry.npmjs.org/ 的服务器上下包。这个服务器在国外,因此下包速度会非常慢。

解决方案:把 npm的下包地址,从国外的服务器切换为国内的服务器。

检查当前的下包地址:
npm config get registry
把下包的地址切换为国内的淘宝服务器
npm config set registry=https://registry.npm.taobao.org/

npm初始化
1.进入到项目所在的根目录下,启动小黑窗(建议:按下shift键,点击右键,在弹出的菜单中选择 “在此处打开命令行”)
2.输入如下命令:

npm init --yes
// --与yes之间没有空格, -- 与init之间有空格
// 或者是 npm init -y

安装包

安装命令: npm i 包名

使用包

格式是:const 常量名 = require('包名') 这个格式与引入核心模块的格式是一样的。

全局安装nrm包

nrm的作用

  1. nrm 这个工具是帮助我们切换安装包的来源的。因为下载包时,默认是从npm官网(国外的网站)下载,速度可能会比较慢,我们可以手动去切换安装来源。

不应该只限于某个具体的项目,所以我们采用全局安装的方式来安装它。
nrm包的地址:https://www.npmjs.com/package/nrm

下载使用的操作步骤

共三步

第一步: 全局安装  npm install nrm -g
第二步:列出所有的源信息(*)标注的就是当前使用的源 nrm ls
第三步:根据需要切换源。例如:指定使用taobao源。nrm use taotao

接下来,正常安装你需要的包

全局安装nodemon包

背景

每次修改了代码,要想代码生效都需要重新运行命令,非常麻烦昂:
有没有一个工具会自动检测到我们的修改并自动重新运行我们的代码呢?有,它叫nodemon。

作用

它能帮我们自动检测到我们的代码的修改,并自动重新运行我们的代码

安装 nodemon

通过npm包管理工具来进行安装。
在任意位置 打开一个小黑窗,输入如下命令:

npm install -g nodemon 回车。

此操作需要联网,根据网络速度所耗时间不同。如果这个命令执行完成并没有报错,就是说明安装成功了。

使用nodemon

等待安装成功之后,使用方法也非常简单:在命令中,使用nodemon来代替node。

// 原来是:node server.js
// 现在是: nodemon server.js

它的好处在于会自动监听server.js这个文件的变化,如果变化了,就会重新自动再去运行。相当于是如下伪代码:

while(server.js 变化了){
 node server.js
}

说明:
● 它是一个第三方的包(其它程序员写的工具)
● 之前的node server.js还是可以用的。

可能会出现的错误

运行nodemon,如果报错如下:
2022-04-26T09:34:43.png
● 解决办法是:
○ 管理员方式,打开命令行(powershell)窗口
○ 执行 set-ExecutionPolicy RemoteSigned;
○ 在出现的选项中,输入 A,回车。即可
如果报错如下
2022-04-26T09:35:15.png
解决办法,重启vscode,win7可能要重启电脑。

全局安装serve包

它用来快速生成静态网页服务器
安装:

npm i -g serve

开发依赖和生产依赖

在本地安装包时,表示我们这个项目要用到这个包,换句话说,我们这个项目要想成功运行,要依赖于这些个包。

但在,具体在项目进行的哪一阶段依赖于这些包呢?也有具体的差异。

本地开发 ----> 上线运行
image.png

操作

这两种依赖关系,在具体操作的过程中,有如下区别

保存到开发依赖(devDependencies)
npm install 包名 --save-dev
// 或者 npm install 包名 -D

通过这种方式安装的包出会现在package.json文件中的devDependencies字段中。

保存到生产依赖(dependencies):
npm install 包名
// 或者 npm install 包名 -S
// 或者 npm install 包名 --save

通过这种方式安装的包出会现在package.json文件中的dependencies字段中

技巧

● 加了-D : 开发依赖,这就表示这个工具包只在开发项目时候要用,项目开发完成就不需要
● 不加-D: 生产依赖,这就表示这个工具包在项目做完了之后也要用

npm包从创建到发布

背景

在工作中我们积累了一些自己的功能代码。这些功能代码可以在其它项目中重复使用,此时我们就可以选择把代码打包放在[npm]上,在需要要使用的项目中,通过npm install去下载下来。

npm项目初始化

在本地磁盘上创建一个空项目,取文件夹名为myNpm。注意请先去npm网官去确定一下,这个项目名是否已经被占用了。(如果这个名字已经被占用了,则你是无法向npm上上传的)。

检查方式

npm view 包名
# 这个命令用来查看 某个包的信息
# 如果返回404,说明这个项目名在npm官网上找不到,此时你就可以使用。
# 否则,说明不可用。
很确定地告诉你,myNpm这个包已经被别人占用了,你需要去自己用另一个名字哈。
npm init --yes

命令来创建一个package.json文件,对你项目myNpm信息进行设置。

完成功能开发

正常开发,完成你的代码。在默认情况下,index.js是这个项目的入口文件。

下面是一个最简单的示例:

//tools.js
const relativeTime = (oldTime) => {
  const t = new Date(oldTime)
  // Date.now():现在的时间戳(毫秒)
  // t.getTime():旧时间的时间戳(毫秒)

  const diff = Date.now() - t.getTime() // 相隔多少毫秒
  // Math.floor 向下取整: 1.7年 ---> 1年前
  const year = Math.floor(diff / (1000 * 3600 * 24 * 365))
  if (year) {
    return `${year}年前`
  }
  const month = Math.floor(diff / (1000 * 3600 * 24 * 30))
  if (month) {
    return `${month}月前`
  }
  const day = Math.floor(diff / (1000 * 3600 * 24))
  if (day) {
    return `${day}天前`
  }
  const hour = Math.floor(diff / (1000 * 3600))
  if (hour) {
    return `${hour}小时前`
  }
  const minute = Math.floor(diff / (1000 * 60))
  if (minute) {
    return `${minute}分钟前`
  } else {
    return '刚刚'
  }
}

const formatDate = (dateTime) => {
  // console.log(date)
  // date = new Date();
  const date = new Date(dateTime) // 转换成Data();
  console.log(date)
  var y = date.getFullYear()
  console.log(y)
  var m = date.getMonth() + 1
  m = m < 10 ? '0' + m : m
  var d = date.getDate()
  d = d < 10 ? ('0' + d) : d
  return y + '-' + m + '-' + d
}



// 通过module.exports来导出模块
module.exports = {
  formatDate,
  relativeTime
};

切换当前npm源到官网

由于我们需要把包上传到npm上,所以要先确保当前的npm源是npmjs.org。与之相关的命令有如下两条。

(1)查看当前的npm的registry配置.

npm config get registry 
# 查看当前的npm的registry配置,确保是https://registry.npmjs.org

# 如果不是,可以通过如下命令来设置
npm config set registry https://registry.npmjs.org 
# 手动设置registry

(2)或者使用nrm工具来设置:

连接npm

npm adduser

这个命令需要输入四个信息以供连接上npmjs:

  • 用户名
  • 密码
  • 邮箱(是你在npmjs官网上注册时使用的信息)
  • 校验密码。它会向你的邮箱发邮件
如果你已经不是第一次连接了,这一步是可以省略的。

你也可以通过如下命令检查自己是否连接成功了。

> npm who am i

如果成功了,则可以进行最后一步了:publish

如果想退出:

npm logout

把包上传到npm

命令: npm publish

如果成功:

-----------------------------------
npm notice
npm notice package: tool61@1.0.0
npm notice === Tarball Contents ===
npm notice 1.3kB index.js
npm notice 220B  package.json
npm notice === Tarball Details ===
npm notice name:          tool61
npm notice version:       1.0.0
npm notice package size:  855 B
npm notice unpacked size: 1.5 kB
npm notice shasum:        3bfba7bc92e242810a850ac39ded7ebe992a6d9c
npm notice integrity:     sha512-VoRuxxbcGzXen[...]v3tKWYUT1B1AQ==
npm notice total files:   2
npm notice
+ tool61@1.0.0

出错的可能是:

  • 这个包名被别人先用了。
  • 包的版本号不对:每次publish时,包的版本号都应该要大于之前的版本号。
  • 文件过大。你可能需要创建.npmignore文件来设置在打包时要忽略哪些文件。如下是一个demo.
# .npmignore
/node_modules
npm-debug.log
/src
/examples
/build

如果没有报错,则表示一切ok,你可以用你的帐号密码登陆npm,去查看你名下的package是否有了myNpm

下载使用

通过npm install 包名即可来安装包。 然后,告诉你的小伙伴们去下载使用吧。

删除包

npm unpublish --force //强制删除

如果你的包没有什么用处,建议删除掉,以节约公共资源。

更新包

  1. 修改代码,保存。
  2. 更新版本号。可直接在package.json中修改:只能改大,不能改小。
  3. 重新publish

拓展:npm包的问题的问答

为什么要把自己的代码上传到npm上?

  • 优秀的代码供所有人复用
  • 提升职场竞争力 ----- 在团队其它同事没有做,你做了!
  • 有了这个目标,我们写项目(写代码)时,就会更加考虑代码的通用性。

优秀的代码从哪里来?

  • 自己写的,同事写的,总结别人....

把代码上传到npm上去,有格式要求吗?

有,必须要是的格式

包是什么格式?

格式:

  • 一定要有   package.json这个文件。 它就是用来对包进行整体说明。(name,  version, description, author, dependencies, ......). npm init --yes
  • 有自己的代码文件。这个代码文件要在package.json中的main中声明。

在上传到npm之前,我们需要切换镜像吗?

需要,我们必须要把代码上传到npm的官网。

通过 nrm use npm 来切换

在上传时,需要登陆吗?

需要,在命令行中登陆。 npm adduser  这一个操作只需要做一次

在上传时,对包名有约定吗?

有。 1. 不能与现有包重名;2. 包名只能是小写字母+数字+中划线

上传的命令是什么?

npm publish

上传出错的可能性有?

  1. 你的帐号还没有通过验证 (在你登记的邮箱里,会收到一封邮件,要去点击确认)。 qq邮箱好像不支持在手机中操作, 建议在pc中浏览器里进行操作。
  2. 没有登陆, 没有做npm adduser
  3. 网不好!

如何对包进行版本更新?

  1. 更新代码,准备重新发布
  2. 升级版本号(只能改大,不能改小)。 在 package.json中去修改version值
  3. npm publish

如何去下载包

命令:npm i 包名

  1. 在另一个项目中去下载包
  2. 为了提升下载速度,我们会切换镜像到taobao。

虽然我们上传是传到npm官网,但是,它会自动同步(例如:每隔15分钟就会通过其它镜像最新的包的信息)给其它的镜像 --- taobao, cnpm.....

require的加载机制

在我们使用一个模块时,我们会使用require命令来加载这个模块。以加载一个自定义模块为例,require(文件名)的效果是:

  1. 执行这个文件中的代码
  2. 把这个文件中的module.exports对象中的内容返回出来。

以如下代码为例:

// moudule1.js
var a = 1;
var b = 2;
console.log(a+b);
var c = a+b;
module.exports = {
    data: c
}

在index.js中使用模块

// index.js
const obj = require('./moudule1.js');
console.log(obj);

//这里的obj对象就是moudule1.js中的module.exports对象

require加载规则:

  • require 优先加载缓存中的模块。同一个模块第一次require之后,就会缓存一份,下一次require时就直接从缓存中去取。
  • 如果是加载核心模块,直接从内存中加载,并缓存

    • 加载核心模块的格式是 const xxx = require("模块名") 。不能写相对路径!
  • 如果是相对路径,则根据路径加载自定义模块,并缓存

    • require('./main')为例( 省略扩展名的情况)
    • 先加载 main.js,如果没有再加载 main.json,如果没有再加载 main.node(c/c++编写的模块),找不到就报错。
  • 如果不是自定义模块,也不是核心模块,则加载第三方模块
    require('XXX')为例:

    • node 会去本级 node_modules 目录下的xxx文件夹中找xxx.js ----> xxx.json ----> xxx.node(找到一个即返回),找到并缓存。
    • 如果找不到,node 则取上一级目录中的node_modules下找 , node_modules/xxx 目录,规则同上
    • 如果一直找到代码文件的文件系统的根目录还找不到,则报错:模块没有找到。

在module.paths命令中可以看到搜索路径中包含node_modules这个文件夹

附:npm 常用命令

  • 查看
npm -v                  // 查看npm 版本
where node               // 查看node的安装目录
where npm               // 查看npm的安装目录
npm root -g             // 查看全局包的安装目录
npm list -g --depth 0   // 查看全局安装过的包
  • 升级 npm
npm install npm --global  // 简写成 -g
npm install npm -g
  • 初始化 package.json
npm init -y // 或者是npm init --yes
  • 安装第三方包
// 安装当前目录下package.json中列出的所有的包
// 如果之前安装了包,又在package.json中手动删除依赖
// 它相当是删除包
npm install

// 全局安装
npm install 包名 -g  // npm install -g 包名 

// 本地安装,没有指定版本,默认安装最新的版本
npm install 包名

// 一次安装多个包,空格隔开
npm install 包名1 包名2 包名3

// 安装指定版本的包
npm install 包名@版本号

// 简写。把install简写成 i
npm i 包名
  • 删除已安装的包
npm uninstall 本地安装的包名
npm uninstall 全局安装的包名 -g
  • 设置npm的register
    如果你不想用 nrm ,下面这个原生的命令也可以切换镜像源(从哪里下载包)。
npm config set registry https://registry.npm.taobao.org

## 所有npm i 包 都会从taobao的镜像去下载。
## 配置后可通过下面方式来验证是否成功
npm config get registry

express

Express 是一个基于 Node.js 平台,快速、开放、极简的 web 开发框架。

  • 框架:是一个半成品,用来快速解决一类问题;库就是工具集,使用非常灵活) (框架有:bootstrap, lay-ui, express, vue, react ; 库:zepto.js , jQuery, day.js, underscore, lodash, art-template, axios, echart.....)
  • web 开发: 对不同的请求能够显示页面;提供接口服务;
  • 对于node.js来说,Express 是一个第三方模块,有丰富的 API 支持,强大而灵活的中间件特性
  • Express 不对 Node.js 已有的特性进行二次抽象,只是在它之上扩展了 Web 应用所需的基本功能

理解:中间件

  • 给用户提供更好的服务
  • 可方便的拆卸

创建项目并初始化

  • 创建一个全新的文件夹,假设名字为 learn-express(目录名不要有汉字,也不要某个包的名字),在此目录下运行npm init -y 命令来生成package.json文件

下载express包

  • 与安装其他的第三方包一致,本地安装npm i express

注意

  • 项目目录名字不要取中文,也不要取为express
  • 如果安装不成功:
    ○ 换个网络环境
    ○ 运行下npm cache clean -f,再重新运行下载命令试试

快速创建web服务器

在项目根目录下新建一个js文件,例如app.js,其中输入代码如下:

// 0. 加载 Express
const express = require('express')

// 1. 调用 express() 得到一个 app
//    类似于 http.createServer()
const app = express()

// 2. 设置请求对应的处理函数
//    当客户端以 GET 方法请求 / 的时候就会调用第二个参数:请求处理函数
app.get('/', (req, res) => {
  res.send('hello world')
})

// 3. 监听端口号,启动 Web 服务
app.listen(3000, () => console.log('app listening on port 3000!'))

托管静态资源-web服务器

让用户直接访问静态资源是一个web服务器最基本的功能

根目录
├── public
│   ├── css
│   │   └── index.css
│   ├── img
│   │   └── bg.jpeg
│   ├── js
│   │   └── axios.js
│   └── index.html
└── serve.js     # 服务器
  • 例如,如上url分别是请求一张图片,一份样式文件,一份js代码。我们实现的web服务器需要能够直接返回这些文件的内容给客户端浏览器。

忽略前缀

// 加载 Express
const express = require('express')

// 1. 调用 express() 得到一个 app
//    类似于 http.createServer()
const app = express();

// 2. 设置请求对应的处理函数
app.use(express.static('public'))


// 3. 监听端口号,启动 Web 服务
app.listen(3000, () => console.log('app listening on port 3000!'))
  • 此时,所有放在public下的内容可以直接访问,注意,此时在url中并不需要出现public这级目录。在public下新建index.html,可以直接访问到。

限制前缀

// 限制访问前缀
app.use('/public', express.static('public'))
  • 这意味着想要访问public下的内容,必须要在请求url中加上/public

路由和接口

格式

const app = express();

// 定义路由
app.METHOD(PATH, HANDLER)

其中:

  • app 是 express 实例 。(const app = express())
  • METHOD 是一个 HTTP 请求方法。 全小写格式。如:post,get,delete等
  • PATH 是请求路径(相当于在http模块中用到过的 url.parse(req.url).pathname)

express写get接口

get无参数

const express = require('express');
const app = express();
app.get('/get', function(req, res) {
  // 直接返回对象
  res.json({ name: 'ceshi' });
});
app.listen('8088', () => {
  console.log('8088');
});

注意:
res.json()是express提供的方法。

get接口有参数

express框架会自动收集get类型的接口从url地址中传递的查询字符串参数,并自动保存在req对象的query属性中。我们直接来获取即可。

const express = require('express');
const app = express();
app.get('/get', function(req, res) {
  // 直接返回对象
  console.log(req.query);
  res.send({ name: 'abc' });
});
app.listen('8088', () => {
  console.log('8088');
});

注意:

  • req.query属性是express框架额外提供的属性

post接口-普通键值

post接口与get请求不同在于:它的参数一般是通过请求体来传递的。根据传递的参数的格式不同,分成三种情况来说

  • 传递普通键值对
  • 传递form表单(涉及文件上传)
  • 传递json

普通键值对参数

具体来说当请求头的content-type为x-www-form-urlencoded时,表示上传的普通简单键值对 。

// 1. 使用中间件
app.use(express.urlencoded());

app.post("/add",function(req,res){
// 2. 可以通过req.body来获取post传递的键值对    
// res.json是express提供的一个函数,用来返回一个json数据给客户端,同时会结束请求
// 类似于res.end, res.send()
    res.json(req.body)
})

注意:

  • app.use(....)之后,在res.body中就会多出一个属性res.body。
  • extended: false:表示使用系统模块querystring来处理传入的参数,也是官方推荐的
  • extended: true:表示使用第三方模块qs来处理传入的参数.

post接口-json格式的参数

在post传递参数时,如果要传入的参数比较复杂(多级嵌套),则可以使用json格式上传。

app.use(express.json());
// 会自动加入req.body属性,这个属性中就包含了post请求所传入的参数

// 用来处理JSON格式的数据
app.post('/postJSON',(req,res)=>{
    // 后端收到post传参
    console.log(req.body);
    
    res.send('/postJSON')
})

post接口-form-data文件上传

如果post涉及文件上传操作,则需要在服务器端额外使用第三方multer这个包(不属于express)来获取上传的信息。
Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件

enctype="multipart/form-data"

步骤

1.安装包

npm install multer

2.使用

// 1. 引入包
const multer = require('multer');
// 2. 配置
const upload = multer({dest:'uploads/'}) // 上传的文件会保存在这个目录下
// uploads表示一个目录名,你也可以设置成其它的

// 3. 使用
// 这个路由使用第二个参数 .upload.single表示单文件上传, 'cover' 表示要上传的文件在本次上次数据中的键名。对应于前端页面上的:
//  <input type="file" name='cover'/>

app.post("/postfile",upload.single('cover'), function(req,res){
    // req.file 记录了文件上传的信息
    // req.body 记录了其它普通参数(非文件)的信息
      // 其它操作
})

说明:

  • 如果当前目录下没有uploads,它会自动创建uploads这个文件夹
  • upload.single只是处理了文件的上传。你仍可以通过req.body来获取其它参数

后端框架代码

2022-04-29T02:54:58.png

发表评论