Node.js详解:node npm express(JavaScript)

Node.js

使用javascript借助node.js可以做后端开发

node.js是一个基于chrom V8引擎的javascript运行环境

官方网址为:https://nodejs.org/zh-cn/

  • js代码在浏览器运行可以做前端开发
  • js代码在node.js运行可以做后端开发
  • node.js是一个基于chrom V8引擎的javascript运行环境
  • node.js 中无法调用Dom和Bom等浏览器内置API

1.node.js的适用

  1. 基于express框架,快速构建web应用
  2. 基于Electron框架,构建跨平台的桌面应用
  3. 基于restify框架,快速构建API接口项目
  4. 读写和操作数据库
终端

计算机实现人机交互的方法,利用终端可以知道所安装node的版本号

windows+R输入cmd打开终端,输入node -v

总结终端的部分快捷命令:

1.终端将命令行从C盘转换为D盘:

D:

2.同一盘下文件路径转换:

cd+空格+Path

3.运行js代码:

node+path

4.快速定位到文件所处路径:

在文件所处目录按住shift右键打开powershell窗口

2.fs文件系统模块

由node.js官方提供用来操作文件的模块

导入fs模块:
const fs=require('fs')//导入fs模块
fs.readFile():

读取指定文件中的内容

示例代码:

const fs=require('fs')
//参数1:读取文件的存放路径
//参数2:读取文件时候采用的编码格式,一般默认utf8
//参数3:回调函数,拿到读取失败和成功的结果err和dataStr
fs.readFile('./1.txt','utf8',function(err,dataStr) {
    console.log(err);//读取成功,输出err为null
    console.log(dataStr);//输出读取的数据,若读取失败的话,输出为undefined
})
fs.writeFile():

向指定文件中写入内容

const fs=require('fs')
fs.writeFile('./1.txt','hello js',function(err) {
    console.log(err);//写入成功,输出err为空
})
  • 可以根据err是否为null判断读取/写入成功还是失败
处理路径问题:

提供完整存放路径,可以解决路径拼接问题,但是移植性较差,不利于维护,使用__dirname更好。

path路径模块

导入path

const path=require('path')

1.path.join代码示例

const pathStr=path.join('/a','/b/c','../../','./d','e')//\a\b\d\e||../表示消除前一层路径

实际使用

fs.readFile(path.join(__dirname,'需要拼接的路径'))

2.path.basename():获取路径中的文件名

const path=require('path')
const fpath='/a/b/c/index.html'
const fullname=path.basename(fpath)
console.log(fullname)//输出index.html

也可以获取删除扩展名后的文件名

const path=require('path')
const fpath='/a/b/c/index.html'
const nameWithoutExt=path.basename(fpath,'path')
console.log(nameWithoutExt)//输出index

获取路径中的文件扩展名

  • path.extname()
const path=require('path')
const fpath='/a/b/c/index.html'
const fext=path.extname(fpath);
console.log(fext)//输出.html

3.http模块

1.关于客户端和服务器:

网络节点中,负责消费资源的电脑,叫做客户端;负责对外提供网络资源的电脑,叫做服务器。

Http模块是用来创建web服务器的模块。通过其提供的http.createServer()把普通的电脑编程web服务器

导入http(创建web服务器):

const http=require('http');
2.进一步理解Http模块的作用

安装服务器软件(例如IIS,Apache),把普通的电脑变成一台Web服务器

3.服务器相关概念

1.IP地址
特殊ip地址:127.0.0.1 这个地址可以把电脑既作为服务器又作为客户端

2.域名

3.端口号
每个服务对应一个端口号

4.创建最基本的web服务器

基本步骤:

  1. 导入http模块
const http=require('http');
  1. 创建web服务器实例
const server=http.creatServer();
  1. 为服务器实例绑定request 事件
server.on('request',(req,res)=> {
    console.log('someone visit our web server.')
})
  1. 启动服务器
server.listen(80,()=> {
    console.log('http server running at http://127.0.0.1')
})
const http=require('http');
const server =http.createServer();

server.on('request',function(req,res){
    console.log('Someone visit our web server');

})
server.listen(80,function(){
    console.log('server running at http://127.0.0.1:80');
})
  1. req请求对象

服务器接收到客户端的请求,调用通过server.on()为服务器绑定的Request事件处理函数。
如果想在事件处理函数中,访问与客户端相关的数据或属性,见下

server.on('request',(req)=>{
    const url=req.url//获取请求的url地址
    const method=req.method//
    const str=`Your request url is ${url},and request method is ${method}`
    console.log(str);

})
  1. 解决中文乱码问题

res.setHeader('Content-Type','text/html;CHARSET=UTF-8')

5.根据不同的url响应不同的Html内容

实现步骤:

  1. 获取请求的url地址
  2. 设置默认响应内容为404NOT FOUND
  3. 判断用户请求的是否为/或/index.html 首页
  4. 判断用户请求的是否为/about.html关于页面
  5. 设置Content-Type 响应头,防止中文乱码
  6. 使用res.end()把内容响应给客户端
const http=require('http');
const server =http.createServer();

server.on('request',(req,res) =>{
    const url=req.url;
    let content='<h1>404 Not found</h1>'
    if(url=='/'||url==='/index.html') {
        content='<h1>首页</h1>'
    } else if(url==='/about.html') {
        content='<h1>关于页面</h1>'
    }
    res.setHeader('Content-Type','text/html; charset=utf-8')
    res.end(content)
    console.log(1);

})
server.listen(80,function(){
    console.log('server running at http://127.0.0.1:80');
})

4.模块化

把大文件拆分成独立化并相互依赖的小文件

模块化规范
1.根据模块来源:
  1. 内置模块
  2. 自定义模块
  3. 第三方模块:
2.加载模块

加载内置模块

const fs=require('fs')

加载用户的自定义模块

const custom=require('./custom.js')//可以省略.js后缀名

加载第三方模块

const moment=require('moment')

当使用require时,加载其他模块会执行加载的其他模块的代码

3.模块作用域

防止了全局变量污染的问题

4.向外共享模块作域中的成员
  1. module对象(存储了和当前模块有关的属性)
  2. module.exports对象(将模块中的成员共享出去)
5.向外共享成员方法
module.exports.username='zs'
const age=20
module.exports.sayHello=function() {
    console.log('Hello!');
}
module.exports.age=age
6.注意点
  • 使用require方法导入模块时,导入的结果是,永远以module.exports指向的对象为准:如下->打印的为新对象
module.exports.username='zs'
module.exports.sayHello=function() {
    console.log('Hello!');
}
//让module.exports指向一个新的对象
module.exports= {
    nickname:'小黑',
    sayHi() {
        console.log('Hi!');
    }
}

7.exports 对象

默认情况,exports和module.exports指向同一个对象

8.exports和module.exports的使用误区
  • 不建议一个模块同时使用

  • 使用requir()导入模块时,得到的永远是module.exports指向的对象:

实例:

const username='zs'
exports.username=username
module.exports= {
    gender:'男',
    age:22
}
console.log(exports);//uesrname
console.log(module.exports);//gender,age
const username='zs'
exports.username=username
console.log(exports);//username
console.log(module.exports);//username
module.exports=exports
9.CommonJS中的模块化规范
  1. module代表当前模块、

  2. module.exports时对外接口

  3. require()方法用于加载模块

3.npm与包

->3.1 包

包:node.js中的第三方模块又叫包,由第三方个人或团队开发出来的,免费使用,基于内置模块封装出来的,提供了更高级,更方便的API

搜索包(网站):https://www.npmjs.com/

下载包(服务器):https://registry.npmjs.org/

下载包管理工具:

1.npm体验
  • 传统格式化时间做法
function dateFormat(dtStr) {
    const dt=new Date(dtStr)
    const y=dt.getFullYear()
    const m=padZero(dt.getMonth()+1)
    const d=padZero(dt.getDate())

    const hh=padZero(dt.getHours())
    const mm=padZero(dt.getMinutes())
    const ss=padZero(dt.getSeconds())
    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`


}
//补0
function padZero(n){
    return n>9?n:'0'+n

}
module.exports= {
    dateFormat
}
const Time=require('./time')
const dt=new Date()
Time.dateFormat(dt)
const newDT=Time.dateFormat(dt)
console.log(newDT);

在项目中安装包的命令

npm i
  • 格式化时间高级做法(包的用法需要自行查阅)
const moment=require('moment')
const dt=moment().format('YYYY-MM-DD HH:mm:ss')
console.log(dt);
2.

安装指定版本的包

npm i moment@2.22.2

2.包管理配置文件

package.json包管理配置文件

如何记录项目中安装了那些包:

项目根目录中,创建一个叫做package.json的配置文件,记录安装了哪些包,方便剔除node_modules目录之后,在团队成员之间共享的源代码

注意:今后在项目开发中,一定要把node_modules文件夹,添加到.gitignore忽略文件中

快速创建package.json:npm init -y

解决下包速度慢的问题
切换npm的下包镜像源
//查看当前下包的镜像源
npm config get registry
//切换至淘宝镜像
npm config set registry=http://registry.npm.taobao.org/
//检查是否下载成功
npm config get registry
使用nrm小工具切换镜像源更方便
//通过 npm 包管理器,将nrm包装为全局可用的工具
npm i nrm -g
//查看所有可用的镜像源
nrm ls
//将下包的镜像源切换为taobao镜像
nrm us taobao

Express

  • 基于node.js的快速,开放,极简的Web开发框架
  • 与Http模块类似,专门用来创建Web服务器
  • 使用Express可以快速创建Web网站的服务器或API接口的服务器
express使用
1.安装

项目所处目录中,运行

npm i express@4.17.1
2.创建基本的Web服务器
//1.导入express
const express=require('express')
//2.创建web服务器
const app=express()
//3.启动web服务器
app.listen(80,()=> {
    console.log('express server running at http:/127.0.0.1')
})

监听客户端GET请求

app.get('请求url',function(req,res)){}

监听客户端POST请求

app.post('请求url',function(req,res))

把内容响应给客户端

res.send()
3.托管静态资源
3.1. 单个静态资源

express提供了一个非常好用的函数,叫做express.static(),通过它,我们可以非常方便的创建一个静态资源服务器,例如通过以下代码将 public目录下的图片,CSS文件,JavaScript文件对外开放访问了:

app.use(express.static('public'))

代码中的使用方法:

const express=require('express')
const app=express()
//在这里,调用express.static()方法,快速对外提供静态资源
app.use(express.static('./clock'))//此段代码将clock目录下的文件对外开放

app.listen(80,()=> {
    console.log('express server running at http://127.0.0.1');
})

集成终端启动node.js后,浏览器输入http://127.0.0.1/index.html

即可打开clock下的index.html文件。

注意:访问路径中没有存放index.html的目录名clock

所以express.static中的文件夹的名称肯定不会出现在访问路径中。

3.2. 托管多个静态资源目录

多次调用express.static()函数

app.use(express.static('public'))
app.use(express.static('files'))
  • 访问静态资源文件时

例如

const express=require('express')
const app=express()
//在这里,调用express.static()方法,快速对外提供静态资源
app.use(express.static('./clock'))//1
app.use(express.static('./files'))//2

app.listen(80,()=> {
    console.log('express server running at http://127.0.0.1');
})

访问http://127.0.0.1/index.html,得到clock目录下的index.html文件

若把1和2 两个句子调换顺次序,则的到files目录下的index.html文件

3.3. 挂载路径前缀

如果希望在托管的静态资源访问路径之前,挂载路径前缀,使用如下方式:

app.use('public',express.static('public'))

代码示例:

const express=require('express')
const app=express()
//在这里,调用express.static()方法,快速对外提供静态资源
app.use('/abc',express.static('./files'))
app.use(express.static('./clock'))

两个文件目录中都含有index.html文件,此时若访问http://127.0.0.1/index.html,得到的是clock目录下的文件,因为访问files下的文件需要前缀/abc

4.nodemon

编写调试项目代码时,如果修改了项目的代码,则需要手动close掉,再重新启动,非常繁琐。使用nodemon可以监听项目文件的变动,代码被修改后,会自动帮我们重启项目

4.1安装nodemon

终端运行如下命令

npm i -g nodemon

4.2.使用nodemon

将node命令替换为nodemon命令,使用nodemon app.js来启动项目

express路由

  • 路由是客户端的请求与服务器处理函数之间的映射关系
  • express中的路由由三部分组成,分别是请求的类型

请求的url地址,处理函数,格式如下

app.method(path,handler)

路由的匹配过程:请求到达服务器后,先经过路由的匹配,只有匹配成功,才会调用对应的处理函数。匹配时,按照路由顺序进行匹配

express中使用路由最简单的用法, 就是把路由挂载到app上

const express=require('express')
//创建web服务器,命名为app
const app=express()

//挂载路由
app.get('/',(req,res)=> {
    res.send('hello world')
})
app.post('/',(req,res)=> {
    res.send('post request')
})
//启动web服务器
app.listen(80,()=> {
    console.log('http://127.0.0.1')
})
  • 这种方法不建议
模块化路由

方便对路由进行模块化管理,将路由抽离为单独的模块

创建一个路由模块

//1.导入express
const express=require('express')
//2.创建路由对象
const router=express.Router()

//3.挂载具体路由
router.get('/user/list',(req,res)=> {
    res.send('Get user list')
})
router.post('/user/add',(req,res)=> {
    res.send('Add new user')
})

//4.向外导出路由对象
module.exports=router

注册路由模块

//1.导入路由模块
const router=require('./03.router')
//2.注册路由模块
app.use(router)
//注意:app.use()函数的作用,就是来注册全局中间件

为路由模块添加统一的访问前缀

//1.导入路由模块
const userRouter=require('./router/user.js')
//2.注册路由模块,添加统一的访问前缀/api
app.use('/api',useRouter)

中间件

express中间件的格式,本质上就是一个function函数

定义中间件函数

const express=require('express')

const app=express()
//定义一个最简单的中间件函数
const mw=function(req,res,next) {
    console.log('这是一个最简单的中间件函数');
    //把流转关系,转交个下一个中间件或路由
    next();
}

app.listen(80,()=> {
    console.log('http://127.0.0.1');
})
全局生效的中间件:

客户端发起的任何请求,到达服务器之后,都会触发中间件,叫做全局生效的中间件,app.use()

//定义一个最简单的中间件函数
const mw=function(req,res,next) {
    console.log('hgwfuy');
    //把流转关系,转交个下一个中间件或路由
    next();
}
//全局生效的中间件
app.use(mw)

定义全局生效的中间件简化形式

app.use(function(req,res,next){
    console.log('dsger')
    next()
})
中间件的作用

多个中间件,共享一份req和res.基于这样的特性,我们可以在上游的中间件中,统一为req或res对象添加自定义的属性或方法,供下游的中间件或路由进行使用

定义多个全局中间件

局部生效的中间件

不使用app.use定义的中间件

示例:

const mw1=function(req,res,next){
console.log('这是中间件函数')
    next()
}
//mw1这个中间件只在“当前路由中生效”,这种用法属于“局部生效的中间件”
app.get('/',mw1,function(req,res){
    res.send('Home page')

})
//mw1不会影响下面这个路由
app.get('/user',function(req,res){
    res.send('Users page')
})
定义多个局部中间件
app.get('/',mw1,mw2,(req,res)=>{res.send('Home page')})
app.get('/',[mw1,mw2],(req,res)=>{res.send('Home page')})
两种写法对等

中间件的注意事项

  • 路由之前注册中间件
  • 客户端发送过来的请求
  • 调用完next()后,不要再写额外的代码

如果没有配置任何解析表达数据的中间件,则req.body默认等于undefined

感谢阅读!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值