文章目录
前言
node中的三大模块:
1)系统模块 核心模块 node中内置的模块
2)第三方模块
3)自定义模块
安装node:
傻瓜式安装 安装完node,自带node命令
测试node是否OK:
window + r 输入cmd node -v
运行node代码:
1)在vscode上安装一个插件 code runner
2)webstrom / idea 直接运行JS代码
2)通过node命令去运行 node server.js
1 什么是模块?
module就是模块的意思。
在node.js模块系统中,每个文件都被视为一个独立的模块。
node.js采用CommonJS规范
实现了模块系统。
CommonJS规范
规定了如何定义一个模块,如何暴露(导出)模块中的变量函数,以及如何使用定义好的模块。
a)在CommonJS规范中一个文件就是一个模块。
b)在CommonJS规范中每个文件中的变量函数都是私有的,对其他文件不可见的(都是隔离的)。
c)在CommonJS规范中每个文件中的变量函数必须通过exports暴露(导出)之后其它文件才可以使用。
d)在CommonJS规范中想要使用其它文件暴露的变量函数必须通过require()导入模块才可以使用。
2 Node模块导出和导入
2.1 Node模块导出数据几种方式:
- 通过
exports.xxx = xxx
导出 - 通过
module.exports.xxx = xxx
导出 - 通过
global.xxx = xxx
导出
注意点:
无论通过哪种方式导出, 使用时都需要先导入(require)才能使用。
通过global.xxx方式导出不符合CommonJS规范, 不推荐使用。
module.exports = "字符串";
//可以的。返回模块本身
module.exports.msg = '字符串'
//可以的
exports.msg = '字符串'
//可以的
exports = '字符串'
//不行的
导出和导入:
方案一:
导出:
exports.xxx = xxx 或 module.exports.xxx = xxx 可以导出N个数据
导入:
let res = require("./a") res是一个对象,对象中包含了N个数据
方案二: module.exports后面的导出会覆盖前面的导出(覆盖.xxx或之前的)
module.exports = "hello" 导出hello;//只能导出一个数据的意思就是因为会覆盖
导入:
let res = require("./a") res就是一个hello、
导出:
module.exports = { name:"wc",age:100 } 导出一个对象
导入:
let res = require("./a") res就是一个对象
强调:
- 每个文件就是一个模块,在模块里面定义的变量、函数、类都是私有的。
- module 代表的当前模块 ,exports属性,代表向外提供接口(数据)。
require加载模块
,读取并执行一个js文件,然后返回该模块的exports对象
。模块加载的顺序
,按照
代码中出现的顺序
。- 模块
可以多次加载
,第一次加载运行之后,会被缓存
,第2次开始,就从缓存中取,就不会重新加载。
exports 和 module.exports的区别?
1)exports只能通过exports.xx = xx的形式,向外暴露数据。
2)module.exports 可以通过 module.exports.xx = xx的形式,向外暴露数据,也可以通过module.exports = xx的形式,向外暴露数据。
3 自定义模块
自定义的模块,需要使用./
或../
打头。
导入模块时,后缀可以不写。
4 系统(核心)模块
导入系统模块 导入系统模块时,不需要加./
或者../
node内置了很多模块。
//require("http") 导入系统模块 导入系统模块时,不需要加./或者../
let http = require("http")
console.log(http); // 使用方式:http.xx ;本身是对象
let qs = require("querystring")
console.log(qs);
let fs = require("fs")
console.log(fs); // fs.xx
let url = require("url")
console.log(url); // url.xx
在node中,人家内置了非常多的模块,我们直接导入后,就可以使用。
核心模块之fs模块:
fs:filesystem 文件系统 操作文件或目录
url模块
将一个URL字符串转换成对象并返回。
语法:url.parse(urlStr, [parseQueryString], [slashesDenoteHost]);
接收参数:
urlStr: url字符串
parseQueryString: 为true时将使用查询模块分析查询字符串,默认为false
slashesDenoteHost:
默认为false,//foo/bar 形式的字符串将被解释成 { pathname: ‘//foo/bar' }
如果设置成true,//foo/bar 形式的字符串将被解释成 { host: ‘foo', pathname: ‘/bar' }
例:url.parse(http://localhost:3000/phone/goods?name='wc'&age=100")
输出结果:
Url {
protocol: null, 协议
slashes: null,
auth: null,
host: null, 主机(IP或域名) ***
port: null, 端口
hostname: null, 主机名 ***
hash: null,
search: '?name=%27wc%27&age=100%22', searchs查询字符串 ***
query: 'name=%27wc%27&age=100%22', query查询字符串 ***
pathname: '/phone/goods', pathname路径名 ***
path: '/phone/goods?name=%27wc%27&age=100%22', path是路径 路径 = 路径名 + 查询字符串 ***
href: '/phone/goods?name=%27wc%27&age=100%22'
}
url.parse(req.url)
的使用:
req.url
是请求过来的路径。
对象不能跟字符串类型的数据+
拼接,否则对象会变成[object Object]
从而无法使用。
var str = JSON.stringify(obj); 可以将对象转化为字符
let urlObj = url.parse(req.url);//解析url
req.method = req.method.toLowerCase();//得到url中get或post方法
req.pathname = urlObj.pathname;//得到路径名
req.query = qs.parse(urlObj.query) //得到get请求下的url内的查询字符串
req.body = qs.parse(params) //得到post请求下的url内的查询字符串
// req是请求对象,里面有method url path query
console.log(req.method);
console.log(req.pathname);
console.log(req.query);
console.log(req.body);//post方法中的请求体
一般需要调用url里面的pathname
和query
请求参数。
const http = require("http");//载入模块
const url = require("url")
let server = http.createServer((req, res) => {
// req 里面包含非常多的请求信息
// http://localhost:3000/phone/goods?name='wc'&age=100"
// 通过req.url得到的url没有协议,没有域名,没有端口
console.log(req.url); // 获取请求的url /phone/goods?name =% 27wc % 27 & age=100 % 22
// urlObj 解析之后的url 解析之后变成对象了
//好处: 变成对象就可以打点访问时面的属性了 对象.xx
let urlObj = url.parse(req.url)
console.log(urlObj);//解析结果
res.write("<h1>hello client~</h1>")
res.end();
})
server.listen(3000, () => {
console.log(`server is running on ${3000}`);
})
url.format(urlObject)
的使用:
const http = require("http");//载入模块
const url = require("url")//载入模块
let server = http.createServer((req, res) => {
var params = {
protocol: 'https:',
host: 'www.lagou.com',
port: '8080',
hostname: 'www.lagou.com',
hash: '#position',
search: '?name=zhangsan&age=20',
pathname: '/a',
}
// format 格式化 把一个对象格式化成一个串
console.log(url.format(params)); // https://www.lagou.com/a?
name = zhangsan & age=20#position
res.write("<h1>hello client~</h1>")
res.end();
})
server.listen(3000, () => {
console.log(`server is running on ${3000}`);
})
querystring模块
查询字符串。
querystring:模块提供用于解析和格式化 URL 查询字符串的实用工具。 可以使用以下方式访问它: const qs = require("querystring");
qs.parse()
将URL解析成对象的形式。
qs.stringify()
将对象 序列化成URL的形式,以&进行拼接。
const http = require("http");//载入模块
const qs = require("querystring");//载入模块
const url = require("url")//载入模块
let server = http.createServer((req, res) => {
// 请求地址
let urlObj = url.parse(req.url)
// 结果
// Url {................
// }
// console.log(urlObj);
// console.log(urlObj.query); // name=%27z3%27&age=100
// qs 可以解析查询字符串 url.parse中第二个参数为true也可以解析查询字符串
let qsObj = qs.parse(urlObj.query)
console.log(qsObj); // { name: "'z3'", age: '100' }
res.write("<h1>hello client~</h1>")
res.end();
})
server.listen(3000, () => {
console.log(`server is running on ${3000}`);
})
//qs.parse()将URL解析成对象的形式
//qs.stringify()将对象 序列化成URL的形式,以&进行拼接
var params = {
name: 'wangcai',
age: 20
}
console.log(qs.stringify(params));//name=wangcai&age=20
fs模块
File System文件系统
封装了文件或文件夹 相关的api
得到文件与目录的信息:stat
创建一个目录:mkdir
创建文件并写入内容:writeFile,appendFile
读取文件的内容:readFile
列出目录的东西:readdir
重命名目录或文件:rename
删除目录与文件:rmdir,unlink
fs.writeFile();覆盖式,写文件写入内容,没有则先创建文件,在写入。
fs.unlink();删除文件
fs.rename();修改文件
fs.appendFileSync();追加式写入文件
…更详细的功能:传送门
const fs = require("fs")//引入模块
// fs提供的api,基本上都是两套,一套是同步的,一套是异步的
---------------------- 创建一个文件,写入内容,如果没有文件,会自动创建文件
// err 表示如果写入失败了,失败的原因都是err中
// ./ 表示生成在js文件同级
// 第一个参数文件名,第二个参数表示写入的内容 第三个参数是回调函数 回头再调
fs.writeFile("./nameceees.txt","hello fs",function(err){
if(!err){
console.log("写入成功~");
}
});
---------------------- 删除文件
//err回调函数的第一个参数都是err 在node是叫错误优先
fs.unlink("./name.txt",function(err){
if(!err) console.log("删除成功!");
})
---------------------- 修改文件
fs.rename("./name.txt","newName.txt",function(err){
if(!err) console.log("修改成功!");
})
---------------------- 覆盖式写文件
fs.writeFile("./newName.txt","666",function(err){
if(!err){
console.log("写入成功~");
}
});
---------------------- 追加式写文件
fs.appendFileSync("./newName.txt","888",function(err){
if(!err){
console.log("写入成功~");
}
});
events模块
事件处理模块。
const EventEmitter = require("events");或者
const emitter = require("events");
emitter.on(name, f) 对事件name指定监听函数f
emitter.addListener(name, f) addListener是on方法的别名
emitter.once(name, f) 与on方法类似,但是监听函数f是一次性的,使用后自动移除
emitter.listeners(name) 返回一个数组,成员是事件name所有监听函数
emitter.removeListener(name, f) 移除事件name的监听函数f
emitter.removeAllListeners(name) 移除事件name的所有监听函数
emitter.emit()用来触发事件。它的第一个参数是事件名称,其余参数都会依次传入回调函数。
path模块
处理路由的 基本上,用Node写服务器,都会用到此模块。
let path = require("path"); // 导入path 系统模块 内置模块 处理路径
// __dirname 获取当前文件所在的文件夹的绝对路径
let res = path.resolve(__dirname,"a.html") // resolve具备路径拼接的功能
console.log(res); // e:\代码\03-系统模块\a.html
=====================如果是/ 含义就不一样 如果遇到一个/ 表示回到根路径
let res = path.resolve(__dirname,"/a.html") // e:\a.html
console.log(res); // e:\a.html
// let res = path.resolve(__dirname,"/") // e:\ 根路径
// console.log(res); // e:\ 根路径
=====================join纯粹是路径拼接;有没有/都一样
let res = path.join(__dirname,"abc")
console.log(res); // e:\03-系统模块\abc
let res = path.join(__dirname,"/abc")
console.log(res); // e:\03-系统模块\abc
=====================extname获取后缀名
let res = path.extname("a.b.html")
console.log(res); // .html
=====================relative用于将绝对路径转为相对路径
//path.relative(from, to)用于将绝对路径转为相对路径,返回从 from 到 to 的相对路径(基于当前工作目录)。
let res = path.relative("a","a/a.js")
console.log(res); // a.js
path.resolve(__dirname,"a.html")
resolve 在拼接时,如果遇到/ 表示根路径
resolve有两个作用:
1)路径拼接 path.resolve(__dirname,"a.html")
2)如果是/ 含义就不一样 如果遇到一个/ 表示回到根路径
path.join(__dirname,"abc")======= join纯粹是路径拼接;有没有/都一样
path.extname("a.b.html")======extname获取后缀名
path.relative("a","a/a.js")======relative用于将绝对路径转为相对路径
...
vm模块
const vm = require('vm');
let a = 1;
const log = `console.log(a)`;
// eval执行时会查找上下文,不干净的执行
eval(log);
// new Function 是可以产生一个执行环境 不依赖于外层作用域,必须包一层函数 模板引擎中会使用
newFunction
// 模板引擎用的是 new Function + with
let fn = new Function(log);
console.log(fn())
// 让字符串直接执行 并且在沙箱环境中,干净的环境
vm.runInThisContext(log);
http模块
利用http模块创建一台服务器:
// 引入一个核心模块http
let http = require("http");
// 创建一台服务器
let server = http.createServer();
// 注册一个请求事件
server.on("request",(req,res)=>{
// 解决乱码 不需要记
res.writeHead(200,{"content-type":"text/html; charset=utf-8"})
// 给客户端响应数据
res.write("<h1>hello 你好 客户端~</h1>")
// 结束响应
res.end();
})
// 监听一个商品,只要是一个服务,就要监听一个端口
server.listen(3030,()=>{
console.log("server is running on 3030~")
})
5 第三方模块
5.1 下载安装第三方模块
npm npm是一个下载器 当我们安装了node 自带了下载器
要下载第三方,默认是国外下载,配置让去国内下载,nrm
nrm可以换源:
安装nrm npm i nrm -g 只要-g,就可以使用nrm这个命令
nrm use taobao 换成国内源 下载速度会快一点
nrm ls 查看都有哪些源
一个项目, 可能有N个第三方模块,我们就需要一个文件,来记录你项目中都使用了哪些第三方模块,在写项目时,先需要创建这样一个配置文件,它的主要作用就是记录,你的项目中都用到了哪些第三方模块/第三方依赖
。
npm init -y
初始化项目 生会一个配置文件,叫package.json
文件。
此文件会对项目进行描述,主要的用来记录我们项目的依赖(使用了哪些第三方模块)。
生成的配置文件如下:
{
"name": "nodeCode", // 项目的名字
"version": "1.0.0", // 项目的版本
"description": "", // 项目的描述
"main": "01-hello node.js", // 项目的入口
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1" // 配置一些命令
},
"keywords": [], // 项目的关键字
"author": "", // 项目的作者
"license": "ISC" // 项目遵循的协议
"dependencies": {/-------------------------项目依赖/
"jquery": "^3.6.0",
"react": "^17.0.2",
"vue": "^2.6.14"
},
"devDependencies": {/-----------------------开发依赖/
"less-loader": "^10.0.0",
"webpack": "^5.40.0"
}
}
安装好的第三方模块会放在node_modules
这个文件夹中的。
同时生成package-lock.json
用来锁死第三方模块的版本号。
别人使用你的项目时,只要还有package.json
文件就可以通过命令:npm i
把所有第三方模块重新安装好。也就是配置项目所需的运行和开发环境。
模块:一个文件就是一个模块。
包:N个文件,放在一个文件夹中,就形成一个包,安装一jquery,最终就是一个包(依赖)
注意点:package.json文件中, 不能加入任何注释。
安装包:
包(依赖)的类型:
1) 开发依赖devDependencies(webpack)。
在项目开发的过程中需要的依赖,但是项目上线时,不需要了,叫开发依赖。
如:less 把less转成css的依赖 项目时,就不需要了。
安装:npm install webpack -D -D表示安装的依赖是开发依赖。
2) 项目依赖dependencies(vue) npm install vue -S 新版本可以省略。
项目上线时,还需要的依赖,没有这个依赖,项目就运行不了,叫项目依赖。
安装:npm install vue -S -S表示安装的是项目依赖。
3) 同版本依赖peerDependencies。
4) 捆绑依赖bundledDependencies npm pack打包时,可以把有些依赖打包进去。
5) 可选依赖optionalDependencies。
安装项目依赖:
npm i xx -S 或 npm i xx --save
安装开发依赖:
npm i xx -D 或 npm i xx --save-dev
注意点:
1.将项目拷贝给其它人, 或者发布的时候, 我们不会将node_modules也给别人, 因为太大。
2.因为有的包可能只在开发阶段需要, 但是在上线阶段不需要, 所以需要分开指定。
npm i 所有的包都会被安装
npm i --production 只会安装dependencies中的包
npm i --development 只会安装devDependencies中的包
第三方模块express模块
npm i express
使用:
let express = require("express")
let app = express();
app.get("/",(req,res)=>{
res.send("hello 客户端~")
})
app.listen(3333,()=>{
console.log("server is running on 3333")
})
以下所有模块以上方express代码为母板,不在重复写这些内容。
ejs模块
npm i ejs
ejs
:一个模板引擎,默认情况下,你的模板中写的数据都是假数据,一般数据都是来自于数据库的。如果把数据库中的数据取出来,放到需要替换数据
的地方,此时就是一个真数据,这个流程叫服务端渲染
。
使用:
var ejs = require("ejs");// 导入ejs模块
==================================路径写法一
app.use(express.static(path.join(__dirname,"public")))
// 1)告诉express,你的模板在什么地方
app.set("views",path.join(__dirname,"views"));//绝对路径的写法
==================================路径写法二
// 把./views目录设置为模板文件根,html文件模板放在view目录中
app.set("views", "./views");//告诉express,模板放在views下面
==============================================================================
// 设置模板引擎为ejs
// 2)告诉express,你使用的模板引擎是什么 ejs 除了ejs模板引擎之外,还有其它的模板引擎
app.set('view engine', 'ejs')
app.get("/xxx",(req,res)=>{
// res.send("hello express")
// 把数据渲染到模板中 通过res.render就可以渲染模板,同时就可以给模板上绑定数据
res.render('xxx',{msg:"dadaima"});
})
body-parser模块
npm i body-parser
使用:
var bodyParser = require('body-parser')
// 配置bodyParser
app.use(bodyParser.urlencoded({ extended: false }))//告诉express解析表单数据
app.use(bodyParser.json())//解析json数据
//req.body就可以获取post请求的携带的数据
cookie-parser模块
npm i cookie-parser
配置cookie
使用:
const cookieParser = require('cookie-parser')
app.use(cookieParser());//配置cookie
express-session模块
npm i express-session
配置session
使用:
const session = require('express-session')
// 配置session
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
// session是基于cookie的
cookie: { maxAge:60000*10 }
}))
cookie-session模块
npm install cookie-session
配置cookie-session
var cookieSession=require('cookie-session');
app.use(cookieSession({
name: 'lagou',
secret:"lagouadmin",//秘钥
maxAge:1000*60*60*24, // 能活一天
cookie:{
maxAge:1000*60*60*24,
}
}))
bcrypt模块
npm install bcrypt
对用户名进行加密
const bcrypt=require('bcrypt')//对密码进行加密处理
// 比对密码是否正确
_comparePwd(pwd, hash) {
return bcrypt.compareSync(pwd, hash)
}
// 对密码进行加密 传进来password
_createHashPwd(password) {//下划线开头 意味着在内部调 不会出去
return bcrypt.hashSync(password, 10)//哈希值加密
}
// 密码入库之前,需要进行加密
password = this._createHashPwd(password)
multer模块
npm install multer
实现express中文件上传,一般写于中间件
// 之前普通的文本数据,通过body-parser就可以接收 (普通的表单数据)
let multer = require('multer')//上传文件需要这个模块
let path = require('path')
let uploadfile=(req,res,next)=>{
console.log("文件上传");
let fullpath = path.resolve(__dirname, "../public/upload");//指定下载到的路径
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, fullpath)//指定下载到的路径
},
filename: function (req, file, cb) {
let extname = path.extname(file.originalname);//文件后缀
filename = file.fieldname + '-' + Date.now() + extname;//图片名字:
// filename = file.fieldname + extname;//图片名字
cb(null, filename)
}
})
var upload = multer({ storage }).single('companyLogo');//companyLogo是文件的键名
upload(req, res, function (err) {
if(!req.file){// 如果上传文件不存在
delete req.body['companyLogo'];//如果失败就删除它
res.send("如果上传文件不存在,提示这个信息")
next();//表示程序可以继续向下执行
return;
}
if(err){// 如果出现错误,提示
res.send({
code:-1,
message:"图片上传失败"
})
}else{
req.body.companyLogo = filename;//这里只是放入body里它的这个文件名
console.log("我就改个名字");
next();//表示程序可以继续向下执行
}
})
// next();
}
module.exports=uploadfile;
后续还会补充…