node是什么
Node.js是JS的后端运行环境
Node.js 是一个基于 Chrome V8 引擎 的 JavaScript 运行时环境
打开方式
- 直接win+r的方式打开cmd的方式打开
小黑窗 - 在任意目录的最上方路径输入框中输入 cmd 回车接口打开 (推荐)
- 在任意目录中按住 shift键 + 鼠标右键后在弹出菜单中点击 在此处打开命令窗口 或 在此处打开PowerShell窗口即可打开
- 在VSCode中,任意一个js文件上鼠标右键,选择在 集成终端中打开
在node环境中运行js代码
打开小黑窗,输入 node 执行体验.js 回车即可
node后面需要空格 可以直接tab自动填充
终止当前node可以按ctrl+c
复制粘贴都是用鼠标右键
常用操作命令
清空输入 clear或者cls
查看列表 ls/list/dir
进入某个目录 cd 目录名
返回上一个目录 cd ..
回到根目录 cd \
切换历史输入 ⬆ ⬇
文件读取模块
核心模块就是nodejs自带的模块,在安装完nodejs之后,就可以任意使用啦。相当于学习js时使用的Math对象一样
查询官网
nodeapi官网:nodejs.org/dist/latest…
语法
const 变量名(自己随意取) = require('核心模块名');
文件读写模块
const fs = require('fs')
异步读取文件
fs.readFile("./data/01.txt", function(err,data){
// data返回buffer对象(二进制对象),可以通过toString方法转换为正常文字
console.log(err,data.toString());
})
同步读取文件
// try {
// 这里写正常的逻辑代码
// } catch (error) {
// 如何try中的代码报错了,那么这个错误就会被catch捕捉到
// 这个错误可以通过catch的参数获取到
// 所以,这里就是用来做一些错误处理地方
// }
try {
const res = fs.readFileSync("./666.txt")
console.log(4,res);
} catch (error) {
console.log(19,"发生错误了",error);
}
异步写入内容
// 写入成功案例,因为writeFile方法会自动帮我们创建03.txt文件
fs.writeFile("./data/03.txt","等闲变却故人心,故人却道心易变",(err)=>{
if(err){
console.log("发生错误:",err);
return
}
console.log("写入成功");
})
同步写入内容
try {
fs.writeFileSync("./data/04.txt","君不见高堂明镜悲白发,朝如青丝暮成雪;")
console.log("写入成功");
} catch (error) {
console.log("写入失败:",error);
} //同步与异步写入内容都会将之前已有的内容覆盖
异步追加内容
// \n: 表示换行符
fs.appendFile("./data/03.txt","\n何如薄幸锦衣郎,比翼连枝当日愿!",(err)=>{
if(err){
console.log("写入失败:",err);
return
}
console.log("写入成功!");
})
同步追加内容
try {
fs.appendFileSync("./data/04.txt",",奔流到海不复回;")
console.log("写入成功");
} catch (error) {
console.log("写入失败:",error)
}
Path模块
作用:用来处理路径的拼接,分析,取后缀名
常用的方法
__dirname: 获取js文件在node中执行时的绝对路径
Http模块
浏览器 请求 资源 要遵守 http 协议: 请求报文(请求行,请求头,请求体)
服务器 返回 资源 要遵守 http 协议: 响应报文(响应行,响应头,响应体)
一般用来创建web服务器
基本用法
const http = require("http");
const app = http.createServer(function(req,res){
// req(request): 请求报文
// res(response): 响应报文
// 每次浏览器访问服务器的时候,都会触发这个回调函数
console.log("服务器已经在运行了");
// res.end方法用来返回数据给浏览器
res.end("ok")
})
app.listen("8001",()=>{
// listen是用来监听端口号,这里的回调函数只会触发一次
console.log("web服务器启动成功:http://127.0.0.1:8001");
})
req.url
通过 req.url来获取当前请求的url路径
const http = require("http");
const app = http.createServer(function(req,res){
// req:也就是回调函数的第一个参数,一定是请求报文
// res:也就是回调函数的第二个参数,一定是响应报文
//如何知道浏览器访问的路径?
// 答:通过 req.url来获取浏览器访问的路径(不包含基础路径)
console.log(req.url);
// setHeader: 设置响应头,content-type用于设置返回给前端的数据类型
// 数据类型我们如何知道呢?答:通过一个网站查询:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types
res.setHeader("content-type","text/html;charset=utf-8")
// 实现获取用户信息接口
if(req.url === "/admin/user/info"){
let obj = {
nickname: "小明",
userPic: "http://127.0.0.1:8000/123.png"
}
// end方法中只接收字符串或者buffer对象
res.end(JSON.stringify(obj))
}else{
// 设置请求状态码
res.statusCode = 404;
// 注意:返回参数中的404是假的404,只是后端人员为了告诉前端人员错误的原因
// res.end表示请求结束了,并返回数据给前端
res.end("{msg: '请求失败',code: 404}")
}
})
// 端口号自己声明,值的访问0-6万多
// 建议大家,端口号取值4位数
app.listen("8000",()=>{
console.log("服务器启动成功:http://127.0.0.1:8000");
})
res.setHeader()设置响应头解决中文乱码
常见的几种文件类型及content-type
res.end()设置响应体
语法:res.end(响应的数据)end()只能传入buffer或者是String类型的数据
res.statusCode设置状态码
res.statusCode = 状态码,状态码是http协议规定的 状态码: 500 (服务器异常) 404(资源找不到)
批量处理.html中的二次请求
const fs = require("fs");
const http = require("http");
const path = require("path");
let extType = {
".html": "text/html;charset=utf8",
".css": "text/css;charset=utf8",
".js": "application/javascript",
".jpg": "image/jpg"
}
const app = http.createServer((req,res)=>{
// res.end("ok")
// 根据访问文件的后缀名可以动态设置content-type的值
// 如何获取到文件的后缀名呢?
// 答:通过path.extname方法获取文件后缀名
let _url = "./public"+req.url;
fs.readFile(_url,(err,data)=>{
if(err){
console.log("读取失败:",err);
res.setHeader("content-type","text/html;charset=utf8" )
res.end("读取失败!")
return
}
res.setHeader("content-type",extType[path.extname(req.url)] )
res.end(data);
})
})
app.listen("8003",()=>{
console.log("服务器开启成功:http://127.0.0.1:8003");
})
web服务器通过req.method获取当前请求的类型
/**
* 静态资源:返回给前端的是一个个文件
* 接口:返回给前端的是数据
*
* nodejs如何启动一个接口
*
* 请求方法:
* 常用的:get,post
* */
const http = require("http");
const app = http.createServer((req,res)=>{
// 如何获取到请求方式:
// 答:可以通过req.method属性获取到
// 需求:实现get请求,请求地址是/api/getBookList,请求参数是bookname,搜索书籍接口
// 获取查询参数
// req.url包含了查询参数
console.log(req.url);
let arrUrl = req.url.split("?");
console.log(22,arrUrl);
if(req.method == "GET"&&arrUrl[0] === "/api/getBookList"){
// 请求地址和方式正确,返回数据给前端
let arr = [
{
name: "红楼梦",
author: "曹雪芹"
},{
name: "三国演义",
author: "罗贯中"
}
]
// arrUrl[1] 的值就是 bookname=三国演义
// 获取查询参数
// URLSearchParams:是一个构造函数,用来将查询字符串转换为对象
// 然后我们就能够通过URLSearchParams的实例化对象的get方法获取到查询的参数的值
// 实例化对象:指的就是new构造函数的返回值,这个例子中指的就是query这个对象
let query = new URLSearchParams(arrUrl[1]);
console.log(42,query) // { 'bookname' => '三国演义' } 这个就相当于前端中的对象的形式{bookname: '三国演义'}
let str = query.get("bookname"); // bookname表示获取对象中键值对应的键名
// filter方法是js中数组的过滤器方法
let newArr = arr.filter(item=>{
return item.name == str;
})
// console.log(41,newArr);
res.setHeader("content-type","application/json;charset=utf8")
res.end( JSON.stringify(newArr) )
}else{
res.statusCode = 404;
res.setHeader("content-type","text/html;charset=utf8");
res.end("{msg: '访问地址获取方式错误',code: 404}")
}
})
app.listen("3000",()=>{
console.log("服务器启动成功:http://localhost:3000");
})
URLSearchParams 解析参数
Post接口
利用postman模拟数据post
let result ="";
req.on("data", (chunk)=>{
// chunk: 就是接收到的前端发送过来的数据片段(或者是完整的)
console.log(123,chunk);
result+=chunk;
})
req.on("end",()=>{
console.log("数据接收完成了:", result);
})
res.end("post接口")
post请求监听data
data事件,每次收到一部分参数数据就会触发一次这个事件。
post请求监听end
end事件,全部的参数数据接收完成之后会执行一次。
node模块化
每个js文件看作是一个模块,并且通过固定的方式向外暴露指定的内容,每个模块通过固定的方式引入
作用
- 能够对一类功能做很好的分类管理
- 能够保护成员不被污染
- 不用考虑导入顺序按需导入
- 可以随时更换模块,维护方便
写法
// 封装加法运算
function add(a,b){
return a+b;
}
module.exports = {
add
}
导出模块化
exports是module.exports的别名
function add(a,b){
return a+ b;
}
// 方式一
exports.add = add;
// 方式二
module.exports = {
// add
// }
// 方法三
module.exports.add = add;
引入自定义模块
const test = require("定义模块的路径.js")
npm管理工具
node的包管理工具地址
npm安装和使用包
- 执行npm init --yes 初始化package.json
- 去npmjs.com网站 搜索 关键字 找到合适的包
- 按照文档完成下载(使用npm install 包名称 下载)
- 通过require引入包
全局安装
命令:npm install -g 包名 或者 npm install 包名 -g
查看全局的node_modules路径
npm root -g // 查看全局包的安装目录
npm list -g --depth 0 //查看全局安装过的包
nodemon依赖包的使用
它能替代node命令去帮我们执行一个js文件,并自动检测到我们的代码如果有修改就会自动重新运行我们的代码
* 作用:nodemon替换node命令,实时监听代码的变化并执行。
* 使用步骤:
* 1、全局下载 npm i -g nodemon (注:i是install的简写)
* 2、可以在任意目录下使用nodemon命令了
* 3、语法:nodemon 要执行的js代码的路径
忽略监控data.json文件,nodemon --ignore data.json server.js
nrm切换安装包的下载源地址
- 第一步: 全局安装 npm install nrm -g
- 第二步:列出所有的源信息 (*)标注的就是当前使用的源 使用 nrm ls 命令可以查看
- 第三步:根据需要切换源 使用 nrm use taobao 切换到taobao源
npm卸载
本地包卸载
- 进入到你想要卸载的包所在的文件夹,到package.json这一层即可
- 打开cmd小黑窗
- 在小黑窗中执行 npm uninstall 包名 简写: npm un 包名 npm un 包名1 包名2
全局包卸载
- 在任意地方打开小黑窗
- 输入 npm uninstall 全局包名 -g 简写:npm un 全局包名 -g npm un 包名1 包名2 -g
开发依赖和生产依赖
--save-dev:表示安装的包是一个开发依赖包,保存到开发依赖(package.json的devDependencies)
--save:表示安装的包是一个生产依赖包,保存到生产依赖(package.json的Dependencies)
用npm发布包
请先去npmjs.com上注册一个用户,并通过邮箱验证
项目初始化: 创建文件夹,小黑窗中输入:npm init --yes
通过 npm view 文件名 检查一下npmjs上是否有同名的包
切换当前npm源到npmjs上: nrm use npm
连接npm: npm adduser (输入npmjs.com上注册时的用户名,密码,邮箱)
把包上传到npm: npm publish
后续更新需要更改版本号才可以publish
npm unpublish 包名称 --force //强制删除
require加载包
加载核心模块,直接从内存中加载,并缓存,同一个模块第一次require之后,就会缓存一份,下一次require时就直接从缓存中去取。
require加载自定义模块,没有扩展名的情况下,查找文件顺序
// 当我们使用require引入模块之后,该模块会别缓存起来,下一次引入的该模块,就是从缓存中获取的
const fs = require("fs");
const fs1 = require("fs");
console.log(fs1 === fs );
// 引入自定义模块
// 引入模块的时候可以省略文件的后缀名
// 省略后缀名后,require是如何查找文件的呢?
// 答:通过如下顺序查找
// 1、找tool文件夹
// 2、找不到,再找tool.js文件
// 3、找不到,再找tool.json文件
// 4、找不到,再从内置模块中找
// 5、找不到,最后就报错啦
// node_modules
// 引入文件的时候建议加上后缀名,这样可以省略查找的过程(加载速度更快)
const tool = require("./02模块化/tool")
加载第三方模块的格式是 const xxx = require("模块名") ,如:require("dateformat") 并缓存
// node 会去本级目录 node_modules下查找dateformat模块
// 如果找不到,则查找上级目录node_modules下查找dateformat模块
// 直到查找到盘符根目录下
// 如果每一级目录都找不到就报模块找不到错误,如果在某一级目录找到了,则停止查找
express框架
npm安装express框架
创建web服务器
// 1、引入框架
const express = require("express");
// 2、创建服务器
const app = express();
// 3、设置回调,响应数据给前端
// 这个斜杠是浏览器访问“127.0.0.1:8080”时的默认路径
// express提供了专门用来定义get接口和post接口方法的
// 分别是:app.get("接口路径", 回调函数)
// app.post("接口路径",回调函数)
app.get("/",(req,res)=>{
// 通过send方法设置响应数据,这个方法会自动根据内容决定响应content-type的值。
res.send("你好,express---666");
})
// 4、监听端口
app.listen("8080")
express使用send()响应内容
常用方法
req.url // 获取请求url
req.method // 获取请求方法
req.query // 获取url传入的查询字符串参数 返回查询参数的对象
req.params // 获取url传入的路由参数
req.body // 获取post请求体中的参数 需要配合下面内置中间件完成
app.use(express.urlencoded()) // x-www-form-urlencoded对象 app.use(express.json()) // json对象
res.send() // 作用类似于http模块中的res.end() 举例:res.send('要响应的数据')
//它会自动增加content-type响应头,支持直接js对象参数作为响应数据 res.send({name:"张三"})
res.json() // 直接将一个js对象或者数据以json字符串返回:res.json({name:"张三"})
res.status() //设置响应状态码: res.status(404)
res.set() // 设置响应头
res.set('content-type','text/html;charset=utf8')
res.set('Access-Control-Allow-Origin', //设置跨域访问
express静态托管资源
const express = require("express");
const app = express();
// 静态文件托管,直接使用express.static方法托管即可,可以托管多份项目
//一般静态资源html页面文件需设置成index.html
// 如何托管多份项目呢?
// 答:app.use方法可以传2参数,第一个参数就是自定义静态资源访问的路径,
// 第二个参数就是express.static用来设置托管项目文件名
app.use("/static",express.static("public"))
app.use("/test",express.static("测试"))
app.listen("3000",()=>{
console.log("服务器启动成:127.0.0.1:3000");
})
文件上传multer
/***
* 需求:实现文件上传的功能
* 1、利用multer中间件来上传,下载multer(mpm i multer)
* 2、引入multer
* 3、利用multer配置上传文件的存储位置
* 4、在定义post接口的时候,要在接口名称和回调函数之间添加一个参数(multer.single('cover')),设置接收文件的字段名
*
* */
const express = require("express");
const multer = require("multer");
// 通过multer配置上传文件的存储位置
const upload = multer({ dest: "uploads/" }) // uploads这个名字可以自己定义
// 创建服务器
const app = express()
// 前端传值:{cover: 文件对象}
// upload.single定义文件上传时的字段名(属性名),这个cover也是后端人员自定义的
app.post("/upload",upload.single("cover"),function(req,res,next){
res.set("Access-Control-Allow-Origin", "*")
res.send({
status: 200,
msg: "上传成功!"
})
})
app.listen("8080",()=>{
console.log("服务器启动成功:http://127.0.0.1:8080");
})
修改上传文件的文件名
const express = require("express");
const multer = require("multer");
// 通过multer配置上传文件的存储位置
let storage = multer.diskStorage({
// 配置文件存储路径
destination: function (req, file, cb) {
cb(null, "tmp/my-uploads")
},
// 配置自定义文件名
filename: function (req, file, cb) {
cb(null, file.fieldname + "-" + Date.now())
}
})
const upload = multer({ storage: storage })
// 创建服务器
const app = express()
// 前端传值:{cover: 文件对象}
app.post("/upload", upload.single("cover"), function (req, res, next) {
res.set("Access-Control-Allow-Origin", "*")
res.send({
status: 200,
msg: "上传成功!"
})
})
app.listen("8080", () => {
console.log("服务器启动成功:http://127.0.0.1:8080");
})
路由中间件
使用场景:接口数量较多时,需要分类别管理,此时就需要用到路由中间件
首页代码
const express = require("express");
const app = express();
// 5、引入user路由
const userRouter = require("./user/userRouter");
// 6、使用user路由
app.use("/admin/user",userRouter)
app.listen("8080",()=>{
console.log("服务器启动成功:http://127.0.0.1:8080");
})
路由页代码
// 用户相关接口(通过路由中间件实现)
// 1、引入express
const express = require("express");
// 2、通过express生成路由对象
const Router = express.Router();
// 3、定义路由接口路径,并定义处理函数
// 登录接口
Router.post("/login",(req,res)=>{
res.send({
status: 200,
msg: "登录成功!"
})
})
// 获取用户信息接口
Router.get("/info",(req,res)=>{
res.send({
status: 200,
msg: {
username: "小明",
age: 18
}
})
})
// 4、导出router模块
module.exports = Router;
路由中间件作用
express中间件是一个特殊的url地址处理函数,一个 express 应用,就是由许许多多的中间件来完成的
- 执行任何代码。
- 修改请求和响应对象。
- 终结请求-响应循环(结束请求)。
- 调用堆栈中的下一个中间件
中间件本质就是一个函数,它被当作 app.use(中间件函数) 的参数来使用
app.use((req,res,next)=>{
let token = true;
// 当我们的判断成功的时候,需要做下一步操作,不成功则不需要做下一步操作,那么成功的时候如何进行下一步呢?
// 答:中间提供了next函数,那么我们只需要调用这个next函数即可
if(token){
// 当token值存在的时候表示用户已经登录
next() //只有显示调用了next()才会进入到下一个中间件或者路由处理函数的执行,
//否则就到此为止
}else{
res.send({
msg: "请先登录!",
code: 500
})
}
})
中间件分类
- 应用级中间件
- 内置中间件
- 路由级中间件
- 错误处理中间件
- 第三方中间件
错误中间件
// 项目中有很多接口,都需要处理错误信息
// 这个错误中间件所有请求都会经过他,因为可以统一封装错误信息
// 错误中间件的作用(所有的接口都会经过错误中间件):用来统一设置返回给前端的错误信息
app.use((err,req,res,next)=>{
res.send({
msg: err.path,
code: 500
})
})
跨域中间件
解决浏览器跨域请求res.set("Access-Control-Allow-Origin", "*")
const cors = require("cors")
app.use(cors())
验证token中间件
const jwt = require("express-jwt")
// token验证中间件
// unless排除不需要验证的路由(接口)
app.use(jwt({
secret: 'heima71', algorithms: ['HS256']
}).unless({ path: ['/user/register', '/user/login'] }));
app.use(function (err, req, res, next) {
// 当token验证失败的时候,err.name的值就等于UnauthorizedError
if (err.name === 'UnauthorizedError') {
res.status(401).send('invalid token...');
}
});
业务代码1
// 用户相关接口
const express = require("express");
const sqlQuery = require("../utils/db");
const Router = express.Router();
// 写业务
// 注册路由(接口)
/**
* 实现注册路由的功能分析
* 1、接收前端传递过来的用户名密码
* 2、判断用户名密码是否为空(不允许空)
* 3、判断用户名是否已存在
* 4、新增用户
*
* */
Router.post("/register", (req, res) => {
// 1、获取用户名和密码
let { userName, userPwd } = req.body;
// console.log(userName, userPwd);
// 2、判断用户名和密码是否为空
if (userName && userPwd) {
// 3、判断用户名是否已经被注册了
sqlQuery(`select * from user where username="${userName}"`, (err, result) => {
console.log(err);
if (err) {
return res.send({
code: 500,
msg: err.message
})
}
// console.log(33, result); // result得到的结果是一个数组,当数组内有数据的时候表示该用户名已经被注册了
// 4、新增用户
if (result.length === 0) {
// 没有被注册
let sql = `insert into user(username,password) values("${userName}","${userPwd}")`;
sqlQuery(sql, (err, result) => {
if (err) {
return res.send({
code: 500,
msg: err.message
})
}
res.send({
code: 200,
msg: "用户注册成功!"
})
})
return
}
// 该用户名被注册了
res.send({
msg: "该用户名被注册了,请求更改!",
code: 201
})
})
} else {
res.send({
code: 201,
msg: "用户名和密码不能为空,请检查!"
})
}
})
// 登录功能
/**
* 1、写好接口的路由
* 2、获取前端传递过来的用户名和密码
* 3、根据用户名和密码查询数据库数据,看是否存在这样的用户
* 4、如果查询有这个用户:code / msg / token
* 考虑token如何生成?要用的到一个插件生成token,jsonwebtoken
*
* */
Router.post("/login", (req, res) => {
// 2、获取用户名密码
let { userName, userPwd } = req.body;
// 3、根据用户名密码查询数据库中是否存在改用户,
// 如果查询结果返回一个数组,且数组长度大于0说明该用户存,则返回登录成功
let sql = `select * from user where username="${userName}" and password="${userPwd}"`;
sqlQuery(sql, (err, result) => {
if (err) {
return res.send({
msg: err.message,
code: 500
})
}
if (result.length > 0) {
return res.send({
code: 200,
msg: "登录成功!",
token: createToken(userName)
})
}
res.send({
code: 201,
msg: "账号或密码错误,请检查!"
})
})
// res.send("ok")
})
// 封装创建token的函数
var jwt = require('jsonwebtoken');
function createToken(username) {
// 设置加密密码
// sign函数中3个参数的说明
/**
* 第一个参数:生成token的数据(我们对用户名进行加密即可)
* 第二个参数:加密的密码(以后解析前端传递过来的token时需要用到)
* 第三个参数:设置token的过期时间
* */
let password = "heima71";
let token = jwt.sign({
username: username
}, password, { expiresIn: 60 * 60 * 24 });
// token前面必须添加"Bearer "字符串,这个字符串用在验证token需要用到的;注意:Bearer后面必须有一个空格在,
return "Bearer " + token;
}
// 导出
module.exports = Router;
业务代码2
// 英雄相关接口
const express = require("express");
const sqlQuery = require("../utils/db");
const path = require("path")
const Router = express.Router();
// 写业务
// 获取英雄列表接口
/**
* 1、获取前端传入的英雄名
* 2、构建sql语句查询数据
* (判断用户是否传递了英雄名,如果没有传,则读取所有英雄数据返回给前端,如果有传,需要根据英雄名查询数据返回给前端)
* 3、利用mysql查询数据并返回即可
*
* */
Router.get("/getHeroList", (req, res) => {
// 获取英雄名字
let { heroName } = req.query;
// 构建sql语句
let sql = `select * from heros`;
if (heroName) {
sql += ` where name="${heroName}"`
}
// 利用mysql查询数据并返回即可
sqlQuery(sql, (err, result) => {
if (err) {
return res.send({
msg: err.message,
code: 500
})
}
res.send({
code: 200,
msg: "获取成功!",
data: result
})
})
})
// 上传头像
/**
* 1、使用multer中间件上传图片,根据文档上传的步骤
*
* 2、上传成功后返回数据给前端
* */
const multer = require('multer')
// const upload = multer({ dest: 'uploads/' })
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
// path.extname(file.originalname)获取文件后缀名
// console.log(55, file);
const filename = Date.now() + '-' + Math.round(Math.random() * 1E9) + path.extname(file.originalname)
cb(null, filename)
}
})
const upload = multer({ storage: storage })
Router.post("/uploadFile", upload.single('file_data'), (req, res) => {
// console.log(req.file);
res.send({
code: 200,
msg: "头像上传成功",
src: "/" + req.file.path
})
})
// 更新英雄数据
/**
* 1、获取前端传递过来的数据(id必传)
* 2、判断id是否存在
* 3、构建sql语句
* 4、根据构建sql语句更新数据即可(mysql模块)
*
* */
Router.post("/updateHero", (req, res) => {
// 1、获取数据
let { id, name, gender, img } = req.body;
// 2、判断id是否存在
if (id) {
// 更新
// 3、构建sql语句
let sql = `update heros set `;
let arr = [];
if (name) {
arr.push(`name="${name}"`)
}
if (gender) {
arr.push(`gender="${gender}"`)
}
if (img) {
arr.push(`img="${img}"`)
}
sql += arr.join(",") + ` where id="${id}"`;
// 4、实现更新
sqlQuery(sql, (err, result) => {
if (err) {
return res.send({
msg: err.message,
code: 500
})
}
res.send({
msg: "更新成功!",
code: 200
})
})
} else {
res.send({
code: 201,
msg: "id为必传值,请检查!"
})
}
})
// 添加英雄数据
/**
* 实现添加英雄分析
* 1、获取前端传递过来的参数
* 2、判断英雄名是否存在
* 3、构建sql语句
* 4、根据sql语句向数据库插入数据完成添加功能
*
* */
Router.post("/addHero", (req, res) => {
let { name, gender, img } = req.body;
if (name) {
// 名字必须存在
let sql = ` insert into heros(name,gender,img) values("${name}","${gender}","${img}") `;
sqlQuery(sql, (err, result) => {
if (err) {
return res.send({
msg: err.message,
code: 500
})
}
res.send({
msg: "新增成功!",
code: 200
})
})
} else {
res.send({
msg: "名字不能为空",
code: 201
})
}
})
// 删除接口 需要配置路由参数
/**
* 实现步骤
* 1、获取前端传递过来的英雄id
* 2、判断id是否存
* 3、构建sql语句,
* 4、进行删除操作
*
* */
Router.get("/delHeroById/:id", (req, res) => {
let { id } = req.params;
if (id) {
// id存在,进行删除操作
let sql = ` delete from heros where id="${id}" `;
sqlQuery(sql, (err, result) => {
if (err) {
res.send({
code: 500,
msg: err.message
})
return
}
res.send({
msg: "删除成功",
code: 200
})
})
} else {
res.send({
msg: "id不能为空!",
code: 201
})
}
})
// 导出
module.exports = Router;
RESTful接口
- RESTful API是目前比较成熟的一套互联网应用程序的API设计理论
- REST本身并没有创造新的技术、组件或服务,REST指的是一组架构约束条件和原则
MySQL
数据库 (database) 是用来组织、存储和管理数据的一个仓库。
开启数据库
-
- phpstudy集成软件管理mysql (小皮面板(phpstudy) - 让天下没有难配的服务器环境! (xp.cn))
-
- Navicat是一个管理MySQL数据的工具 Navicat | 支持 MySQL、MariaDB、MongoDB、SQL Server、SQLite、Oracle 和 PostgreSQL 的数据库管理
sql语句
-- 插入数据
INSERT INTO skin(cname,skin_name) VALUES("后裔","半神之弓"),("后裔","光辉之辰");
# 添加一个学员 新版本语法
insert into student set username='张三疯', sex='男', age=99
-- 查询
--ORDER BY id DESC 按id降序排序 ASC 升序 ORDER BY 排序
--WHERE cname="后裔" 条件语法
SELECT * FROM skin WHERE cname="后裔" ORDER BY id DESC;
# 查询指定数量的数据 select 字段, 字段, … from 表名 limit 开始索引,查询条数
# 从1 索引开始,查询1条同学表数据
select * from student limit 1,1
# 查询SQL - 统计表数据条数 - count()
select count(id) from student
-- 更新
# 一般需要加条件指定更新数据
UPDATE skin set skin_name="精灵王" WHERE id=1;
-- 删除
# 一般需要加条件指定删除数据
DELETE FROM skin WHERE id=1;
mysql模块
- mysql模块(全小写),是一个操作MySQL数据库的第三方模块
- 通过它,可以 在代码中 操作数据库
尝试
/**
* mysql模块:
* 作用:能够让我们通过js代码 轻松操作数据库(可以执行sql语句)。
*
* 如何使用呢?
* 1、初始化环境 npm init -y
* 2、下载mysql包,npm i mysql
* 3、在js文件引入mysql依赖包,开始使用
*/
// mysql的使用
// 1、引入mysql
const mysql = require("mysql");
// 2、创建连接对象
const conn = mysql.createConnection({
host: "localhost", // 主机地址
user: "root", // 数据库用户名(在小皮软件上可以查看)
password: "123456", // 数据库密码(一定要字符串)
database: "hero" // 数据库名字
})
// 3、连接数据库服务器
conn.connect();
// 4、可以操作数据库了(执行sql语句)
// 查询数据
// conn.query("select * from skin", (err,result)=>{
// console.log(result);
// })
// 插入数据
// conn.query("insert into skin(cname,skin_name) values('张三', '法外狂徒')", (err,result)=>{
// if(err){
// console.log( new Error(err.sqlMessage));
// return
// }
// console.log(err,result);
// })
// 更新操作
// conn.query("update skin set cname='李四' where id=3",(err,result)=>{
// if(err){
// console.log(err.sqlMessage);
// return
// }
// console.log(result);
// })
// 删除
conn.query("delete from skin where id=4",(err,result)=>{
console.log(err,result);
})
// 5、关闭连接
conn.end()
使用
一般封装函数模块来调用
function query(sql,callback){
// 1、导入mysql
const mysql = require("mysql");
// 2、创建连接对象
const conn = mysql.createConnection({
host: "localhost",
user: "root",
password: "123456",
database: "hero"
})
// 3、连接数据库服务器
conn.connect();
// 4、操作数据库
conn.query( sql, callback );
// 5、结束连接
conn.end()
}
// 6、导出
module.exports = query;
const query = require("./04-封装mysql语法");
// 调用封装的query函数 并查询数据 正常sql语法即可使用
query("select * from skin", (err,result)=>{
console.log(err,result);
})