node.js入门
模块化
模块化:将大文件拆成独立并互相依赖的多个小模块。可提高代码的复用性,可维护性,实现按需加载。
nodejs遵循CommonJS模块化规范。
模块导入
require加载模块
require
可以加载需要的内置模块、用户自定义模块、第三方模块(包)。
1 | //内置模块 |
require
引入时会直接运行一遍模块的所有代码,并将其放入缓存。例如,若myJS.js
中有一句console.log('hello')
,引入后会直接打印出hello
缓存后的模块不会被重复加载,即多次调用require不会多次执行模块代码
模块导出
模块作用域
模块作用域:在自定义模块中定义的变量、方法等成员,只能在当前模块内部被访问。
通过模块作用域,可以防止不同模块使用相同变量名导致的全局变量污染。
module.exports
js的module
对象存储了当前js文件的有关信息
其中的exports
对象存储着此模块共享成员的信息。通过module.exports
可共享模块内的成员,供外界使用。require()引入自定义模块,得到的就是module.exports
对象。
module.exports
默认为空,可直接挂载对象和内容:
1 | // 写法一 |
两种方式均可挂载数据。
注意:第二种方法更改了module.exports
的指向,会导致先前添加的内容丢失。
exports
一般情况下,module.exports
可简写为exports
,能起到相同作用。但两者并不完全相同,最好不要混用。
两者一起使用时,module.exports
的优先级更高。exports
会失效。
包与npm
包:nodejs中的第三方模块
npm:包管理工具Node Package Manager,通过npm可下载并管理包
引用包时,在终端中输入npm i 名字
安装后,即可直接require('名字')使用
npm日常操作使用:node.js - 短小精悍的npm入门级保姆教程,一篇包会 - 果冻想 - SegmentFault 思否
详细知识:【Node.js】npm与包【万字教学~超超超详细】_npm.js-CSDN博客
fs-读写文件
方法
读取文件:
- 异步读取:readFile
- 同步读取:readFileSync
- 流式读取:createReadStream
写入文件:
异步写入:writeFile(file, data[, options], callback)
- 注意只能创建文件,不能创建路径
同步写入:writeFileSync
异步追加写入:appendFile(file, data[, options], callback)
同步追加写入:appendFileSync(file, data)
流式写入:createWriteStream(file)
普通读写与流式读写:
普通读取是一次性将整个文件内容读取到内存中,然后进行处理。适用于文件较小、可完全放入内存的情况;
流式读取逐块地从文件中读取数据,可以减少内存占用,并且在处理大型文件时更有效率。
普通:
1 | //第一种,用readFile和writeFile |
流式:
1 | //第二种,用流式操作 |
其他方法请参考Nodejs中的fs模块_node安装fs-CSDN博客
path-路径
文件路径错误问题
如果提供的操作路径为相对路径,很容易出现路径动态拼接错误的问题:
代码运行会以node命令执行时所处的目录拼接相对路径,而不是用js文件目录拼接。
解决方法:提供完整路径即可。
直接提供绝对路径
例: C:\Users\username\Documents\files\1.txt
但这种方法移植性差,不利于维护。
__dirname
__dirname表示当前文件所处目录,更方便安全
将上方路径修改为:__dirname+'/files/1.txt'
另外,有变量**__filename
**,可以定位到当前文件名
path
path.join([…paths])
拼接相对路径。起到添加分隔符的效果。由于操作系统的不同分隔符可能不同,所以在填写路径时最好采用此方式。
上方的路径可改为:path.join(__dirname+'/files/1.txt')
1 | const path = require("path"); |
path.resolve([…paths])
将路径或路径片段的序列按照从右到左的顺序解析为绝对路径,并将它们连接在一起,最终返回一个解析后的绝对路径。
若某路径片段是绝对路径(以斜杠
/
开头),则它会被返回,且后续的路径片段会被忽略。如果某个路径片段是相对路径(不以斜杠
/
开头),则它会与之前的路径片段进行连接,直到生成一个绝对路径。所有的路径片段都被解析完毕后,会返回最终的绝对路径。
1 | path.resolve('/foo/bar', './baz'); |
path.basename(path[,ext])
返回路径指向的文件名,若添加后缀名,返回值则会删除后缀名。
path.extname(path)
返回路径指向的文件的扩展名,若无扩展名则返回空字符串。
path.dirname(path)
返回路经指向的目录名。
1 | path.basename('/a/b/c/1.html'); |
其他方法参考[nodejs] path 路径_path.basename-CSDN博客
示例:压缩html文件
通过fs
和path
压缩html文件,删除换行和空格部分,变成一行的形式
1 | const fs = require('fs') |
http-创建web服务器
负责消费资源的电脑叫做客户端,而负责对外提供网络资源的电脑叫做服务器。
通过http模块可以实现创建web服务器,从而对外提供web资源服务。
基础使用
通过以下的简单步骤实现服务器创建:
1 | // 1.引入模块 |
在监听事件的回调函数中,可以通过请求对象(req)和响应对象(res)实现客户端和服务器的交互。
req请求对象:访问客户端属性,便于向服务器请求数据
res响应对象:访问服务器数据属性,便于向客户端返回数据
1 | server.on('request',(req,res)=>{ |
nodejs终端返回内容:
you receive a request
the request URL is /favicon.ico,method: GET
网页返回内容:
设置服务器监听端口可以添加回调函数,如:
1 | server.listen(80,()=>{ |
通过http
和fs
,可以实现访问服务器内部的数据。
以下是一个浏览器访问网页的例子:
1 | const fs = require('fs') |
浏览器访问http://127.0.0.1/html_files/index.html
可得到./html_files/index.html
的内容,若文件内部包含其他路径地址,则会自动访问。若为相对路径,会从当前文件的路径(./html_files/index.html
)进行拼接。
Express
Express 是一款受欢迎的开源 web 框架,构建语言是 JavaScript,可以在 node.js 环境运行。
npm安装:
express: npm install express -g
express命令工具:npm install express-generator -g
Express/Node 入门 - 学习 Web 开发 | MDN (mozilla.org)
基础使用
最基本的结构:
1 | // 引入express |
监听请求
方法:app.method('地址',function(req,res)=>{})
1 | app.get('/',(req,res)=>{ |
express.static()
express.static()
可以用于创建静态资源服务器:
1 | app.use(express.static('public')) |
可以访问public目录中的所有文件。
注意:express在指定静态目录中查找文件,存放静态文件的目录名(public)不会出现在url中
浏览文件时,直接加上文件在静态目录中的路径即可:
./public/index.html
的文件:http://127.0.0.1/index.html
如需托管多个资源目录,多次调用express.static()
即可,express会根据目录的添加顺序查找文件。文件重名时,会根据目录顺序选择优先的文件。
如果需要添加访问路径前缀,可使用此方式:
1 | app.use('/whatcanisay',express.static('public')) |
./public/index.html
的文件:http://127.0.0.1/whatcanisay/index.html
nodemon
nodemon可以实时监听nodejs文件的变化并重启项目。修改代码时不用再频繁close open文件。
npm安装:npm i nodemon -g
启动nodejs文件时,node index.js
改为nodemon index.js
即可
路由
概念
广义上的路由即映射关系。
express中,路由指客户端亲贵和服务器处理函数之间的映射关系。
express的路由由三部分组成:请求类型,请求url地址和处理函数,格式为:
1 | app.METHOD(PATH,HANDLER) |
将路由挂载到app上是一个路由最简单的使用方法。如前文的监听请求。
每个请求到达服务器都需要先经过路由的匹配,匹配成功后才会调用对应处理函数。
匹配时按照路由定义的先后顺序匹配,请求类型url需要同时匹配成功才会调用处理函数。
模块化路由
路由模块示例:
1 | // 1.导入express |
主文件应用即可:
1 | // 导入路由模块 |
中间件
中间件,特指业务处理的中间处理环节。
中间件的概念与格式
express的中间件,本质上是一个function处理函数,格式如下:
1 | // 中间件的形参列表中必须包含next参数,而路由处理参数中只有res,req |
全局生效的中间件:客户端发起的任何请求,到达服务器后都会触发的中间件.
使用app.use()定义即可:
1 | const myf = function(req,res,next){ |
可以连续定义多个全局中间件,服务器会按照定义的先后顺序进行调用。
中间件作用:连续调用多个中间件时共享同一份res和req。可以在上游中间件中,统一为req和res对象添加自定义的属性或方法(res.属性 = 属性
),供下游中间件使用。
局部生效的中间件:不使用app.use()
1 | // 定义中间件函数 |
注意:
- 在路由之前注册中间件;
- 不要忘记next()函数,为防止代码混乱,next()后不要再写额外代码;
- 连续调用多个中间件时共享同一份res和req。
中间件的分类
常见中间件共有5类:
**应用级别中间件:**通过app.use()
,app.get()
,app.post()
绑定到app实例上的中间件.
**路由级别中间件:**通过express.Router()
绑定到router实例上的中间件
**错误级别中间件:**专门捕获异常错误,防止项目崩溃的中间件。必须有四个形参:
1 | app.use(function(err,req,res,next){ |
注意:错误级别中间件必须注册在所有路由之后
express内置中间件:
express.static
:托管静态网站的内置中间件
express.json
:解析json格式的请求体数据(有兼容性)
express.urlencoded
:解析URL-encoded格式的请求体数据(有兼容性):app.use(express.urlencoded({extended:false}))
第三方中间件:npm下载、require导入、app.use()调用
接口
接口是两个独立系统之间同步数据或访问对方程序的途径。
具体来说,通过接口可以将前后端连起来。
一个基本的post/get接口:
1 | // apiRouter.js 路由模块 |
应用在一个基本的服务器上:
1 | const express = require('express') |
CORS解决跨域问题:cors由一系列http响应头组成,这些响应头决定浏览器是否阻止前端js代码跨域获取资源。配置cors可以解除浏览器端的跨域访问限制
npm安装:npm i cors
并在服务器中引用
CORS响应头部:
将Access-Control-Allow-Origin
设为*
可使浏览器允许来自任何域的请求(跨域)。
更多关于cors跨域问题,请参考:使用CORS解决跨域问题 - 简书 (jianshu.com)
实例:基于ajax实现的网页-服务器交互
中间件multiparty:Express—multiparty (图片上传+表单)_express multiparty-CSDN博客
html端的表单提交代码:
1 | // 表单内容 |
api接口部分:
1 | // apiRouter.js 路由模块 |
express的app.js:
1 | const express = require('express') |
SQL
MySQL表的增删改查(基础)_mysql增删改查-CSDN博客
MySQL Workbench 操作详解(史上最细)-CSDN博客
基本使用
sql语法不关心大小写,大小写均可。
增删改查
1 | -- 数据库为my_db_01 数据表为users 包含id, username, password, userstatus四项 |
where, and, or的使用
order by排序
1 | -- asc按id正序排列,不添加参数默认也为正序排列 |
count()统计数目
1 | -- 统计所有userstatus=0的数据的总数目 |
as 为列名称设置别名
1 | -- count会以total为名显示(total可以省略) |