数据库即存储数据的仓库,可以将数据进行有序的分门别类的存储。它是独立于语言之外的软件,可以通过API去操作它。常见的数据库软件有:mysql、mongoDB、oracle、sqlserver。
下载地址:MongoDB Community Download | MongoDB
MongoDB可视化软件下载地址:MongoDB Compass Download | MongoDB
MongoDB数据库工具下载地址:Download MongoDB Command Line Database Tools | MongoDB
在一个数据库软件中可以包含多个数据仓库,在每个数据仓库中可以包含多个数据集合,每个数据集合中可以包含多条文档(具体的数据)。
术语 | 解释说明 |
---|---|
database | 数据库,mongoDB数据库软件中可以建立多个数据库 |
collection | 集合,一组数据的集合,可以理解为JavaScript中的数组 |
document | 文档,一条具体的数据,可以理解为JavaScript中的对象 |
field | 字段,文档中的属性名称,可以理解为JavaScript中的对象属性 |
使用Node.js操作MongoDB数据库需要依赖Node.js第三方包mongoose
使用npm install mongoose命令下载
在命令行工具中运行net start mongoDB即可启动MongoDB,否则MongoDB将无法连接。也可以直接打开数据库软件启动MongoDB。
使用mongoose提供的connect方法即可连接数据库。
mongoose.connect('mongodb://localhost/playground',{
useNewUrlParser: true,
useUnifiedTopology: true }).then(() =>
console.log('数据库连接成功')).catch(err =>
console.log('数据库连接失败', err));
在MongoDB中不需要显式创建数据库,如果正在使用的数据库不存在,MongoDB会自动创建。
1.8.1创建集合
创建集合分为两步,一是对集合设定规则,二是创建集合,通过mongoose.Schema构造函数的实例即可创建集合。
// 设定集合规则
const courseSchema = new mongoose.Schema({
name: String,
author: String,
isPublished: Boolean
});
// 创建集合并应用规则
const Course = mongoose.model('Course', courseSchema); // courses
1.8.2 创建文档
创建文档实际上就是向集合中插入数据。
分为两步:
1.创建集合实例。
2.调用实例对象下的save方法将数据保存到数据库中。
// 创建集合实例
const course = new Course({
name: '张三',
age: '24',
sex: '男',
});
// 将数据保存到数据库中
course.save(function(err,result){
// save方法,通过回调函数,返回添加的结果
if(!err){
console.log(result);
}
});
// 根据表对象,创建一个文档对象,并将该文档对象保存到数据库的数据表中(回调函数方式)
Course.create({name: '张三', age: '24',sex: '男'}, (err, doc) => {
// 错误对象
console.log(err);
// 当前插入的文档
console.log(doc);
});
//根据表对象,创建一个文档对象,并将该文档对象保存到数据库的数据表中(Promise方式)
Course.create({name: '张三', age: '24',sex: '男'})
.then(doc => console.log(doc)).catch(err => console.log(err))
1.8.3 mongoDB数据库导入数据
mongoimport –d 数据库名称 –c 集合名称 –file 要导入的数据文件
找到mongodb数据库的安装目录,将安装目录下的bin目录放置在环境变量中。
1.8.4 查询文档
// 根据条件查找文档(条件为空则查找所有文档)// 返回文档集合
Course.find().then(result => console.log(result))
// 匹配大于 小于
// age:{$lt:30,$gt:18} 不包括18和30
// age:{$lte:30,$gte:18} 包括18和30
User.find({age: {$gt: 20, $lt: 50}}).then(result => console.log(result))
// 匹配包含
User.find({hobbies: {$in: ['敲代码','学习']}}).then(result => console.log(result))
User.find({hobbies: {$all: ['敲代码','学习']}}).then(result => console.log(result))
// 根据条件查找文档 // 返回文档
Course.findOne({name: 'node.js基础'}).then(result => console.log(result))
// $regex用于设置正则表达式搜索
// 通过select方法,限定查询哪些列,默认情况_id都会返回,
// 如果不需要,通过-_id的方式去掉
User.find({name:{$regex:/刘/i}}).select('name sex age -_id').then(result=>{
console.log(result);
})
// 选择要查询的字段
User.find().select('name email').then(result => console.log(result))
// 将数据按照年龄进行排序
User.find().sort('age').then(result => console.log(result))
// 先根据性别升序,再根据年龄降序
User.find().sort('sex -age').then(result => console.log(result))
// skip 跳过多少条数据 limit 限制查询数量
User.find().skip(2).limit(2).then(result => console.log(result))
1.8.5 删除文档
// 删除单个
Course.deleteOne({}).then(result => console.log(result))
// 删除多个
User.deleteMany({}).then(result => console.log(result))
1.8.6 更新文档
// 更新单个
User.updateOne({查询条件}, {要修改的值}).then(result => console.log(result))
// 更新多个
User.updateMany({查询条件}, {要更改的值}).then(result => console.log(result))
1.8.7 mongoose验证
在创建集合规则时,可以设置当前字段的验证规则,验证失败就输入插入失败。
1.required: true 必需要传字段
2.minlength:3 字符串最小长度
3.maxlength: 20 字符串最大长度
4.min: 2 数值最小为2
5.max: 100 数值最大为100
6.enum: ['html', 'css', 'javascript', 'node.js']
7.trim: true 去除字符串两边的空格
8.validate: 自定义验证器
9.default: 默认值
获取错误信息:error.errors['字段名称'].message
1.8.8 集合关联
通常不同集合的数据之间是有关系的,例如文章信息和用户信息存储在不同集合中,但文章是某个用户发表的,要查询文章的所有信息包括发表用户,就需要用到集合关联。
1.使用id对集合进行关联
2.使用populate方法进行关联集合查询
// 用户集合
const User = mongoose.model('User', new mongoose.Schema({ name: { type: String } }));
// 文章集合
const Post = mongoose.model('Post', new mongoose.Schema({
title: { type: String },
// 使用ID将文章集合和作者集合进行关联
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
}));
//联合查询
Post.find().populate('author').then((err, result) => console.log(result));
// 01.导入mongoose包
const mongoose = require('mongoose')
// 02.使用mongoose提供的connect方法即可连接数据库
mongoose.connect('mongodb://localhost/myschool').then(()=>{
console.log('数据库连接成功')
}).catch(err=>{
console.log('数据库连接失败', err)
})
// 03.创建一个表规范
const studentSchema = new mongoose.Schema({
name:String,
age:Number,
sex:String
})
// 04.根据表规范,创建表
// 注意:数据库中会创建一个名为“students”的表
const Student = mongoose.model('Student',studentSchema)
/* // 05.创建文档,就是创建一个表里面的数据
let stu1 = new Student({
name:'张三',
age:20,
sex:'男'
})
// 06.将文档对象添加到数据表中(就是将数据保存到数据库中)
stu1.save(function(err,result){
if(!err){
console.log(result);
}
}) */
// 创建文档和保存文档这两个步骤可以合并,通过:表对象.create()方法
Student.create({
name:'李四',
age:30,
sex:'女'
}).then(r=>{
console.log(r);
}).catch(err=>{
console.log(err);
})
// 添加操作
// 01.导入mongoose包
const mongoose = require('mongoose')
// 02.使用mongoose提供的connect方法即可连接数据库
mongoose.connect('mongodb://localhost/myschool').then(()=>{
console.log('数据库连接成功')
}).catch(err=>{
console.log('数据库连接失败', err)
})
// 03.创建一个表规范
const studentSchema = new mongoose.Schema({
name:String,
sex:String,
age:Number,
hobbies:Array,
email:String,
isVIP:Boolean
})
// 04.根据表规范,创建表
const Student = mongoose.model('Student',studentSchema)
// 05.向数据库中添加数据
Student.create({
name:'小明',
sex:'女',
age:22,
hobbies:['演戏','睡觉'],
email:'[email protected]',
isVIP:false
}).then(r=>{
console.log(r);
}).catch(err=>{
console.log(err);
})
// 查询操作
// 01.导入mongoose包
const mongoose = require('mongoose')
// 02.使用mongoose提供的connect方法即可连接数据库
mongoose.connect('mongodb://localhost/myschool').then(()=>{
console.log('数据库连接成功')
}).catch(err=>{
console.log('数据库连接失败', err)
})
// 03.创建一个表规范
const studentSchema = new mongoose.Schema({
name:String,
sex:String,
age:Number,
hobbies:Array,
email:String,
isVIP:Boolean
})
// 04.根据表规范,创建表
const Student = mongoose.model('Student',studentSchema)
// 05.查询
// 1. 根据条件查找文档(条件为空则查找所有文档)
// find()方法的返回值是数组
/* Student.find().then(r=>{
console.log(r);
}) */
/* Student.find({name:'周杰伦1'}).then(r=>{
console.log(r);
}) */
// 2. 根据条件查找一个文档(条件为空返回第一个文档)
// findOne()方法的返回值是对象
/* Student.findOne().then(r=>{
console.log(r);
}) */
/* Student.findOne({name:'周杰伦'}).then(r=>{
console.log(r);
}) */
// 3. 如果实现模糊查询
// 3.1. 匹配大于 小于
// 查询年龄大于30岁的学生信息
/* Student.find({age:{$gt:30}}).then(r=>{
console.log(r);
}) */
// 查询年龄小于20岁的学生信息
// Student.find({age:{$lt:20}}).then(r=>{
// console.log(r);
// })
// 查询年龄在20到40之间的学生信息
// $gt 是大于 $gte 是大于等于
// $lt 是小于 $lte 是小于等于
/* Student.find({age:{$gte:20,$lte:40}}).then(r=>{
console.log(r);
}) */
// 3.2. $regex用于设置正则表达式搜索
/* Student.find({name:{$regex:/杰/}}).then(r=>{
console.log(r);
}) */
// 3.3. 匹配包含(数组元素是否包含)
// $in 用于匹配数组中是否有指定的元素(是或者关系)
/* Student.find({hobbies:{$in:['学习','唱歌']}}).then(r=>{
console.log(r);
}) */
// $all 用于匹配数组中是否有指定的元素(是并且关系)
/* Student.find({hobbies:{$all:['写歌','唱歌']}}).then(r=>{
console.log(r);
}) */
// 4. 查询指定列
// select()方法,用于查找指定的列,-_id表示查询列中去除_id列
/* Student.find().select('name sex age -_id').then(r=>{
console.log(r);
}) */
// 5. 对查询结果排序
// sort()方法,用于根据指定列排序
/* Student.find().select('name sex age -_id').sort('age').then(r=>{
console.log(r);
}) */
// sort()方法里面的列名,加上减号表示降序
/* Student.find().select('name sex age -_id').sort('-age').then(r=>{
console.log(r);
}) */
// 同时根据姓名和年龄排序
// 这里是先根据性别排序,性别相同的再根据年龄降序
/* Student.find().select('name sex age -_id').sort('sex -age').then(r=>{
console.log(r);
}) */
// 6. 分页查询
// skip 跳过多少条数据 limit 限制查询数量
let pageIndex=3 //页码
let pageSize=2 //每页数量
Student.find().select('name sex age -_id').skip((pageIndex-1)*pageSize).limit(pageSize).then(r=>{
console.log(r);
})
// 修改和删除操作
// 01.导入mongoose包
const mongoose = require('mongoose')
// 02.使用mongoose提供的connect方法即可连接数据库
mongoose.connect('mongodb://localhost/myschool').then(() => {
console.log('数据库连接成功')
}).catch(err => {
console.log('数据库连接失败', err)
})
// 03.创建一个表规范
const studentSchema = new mongoose.Schema({
name: String,
sex: String,
age: Number,
hobbies: Array,
email: String,
isVIP: Boolean
})
// 04.根据表规范,创建表
const Student = mongoose.model('Student', studentSchema)
// 更新操作
// 1. 更新单个
/* Student.updateOne({_id:"61d7aa96c539753f60468bcb"},{
name:'张三',
age:38,
}).then(r=>{
console.log(r);
}) */
// 2. 更新多个
/* Student.updateMany({sex:'女'},{age:18}).then(r=>{
console.log(r);
}) */
// 删除操作
// 1. 删除单个
/* Student.deleteOne({_id:'61d7aa96c539753f60468bcb'}).then(r=>{
console.log(r);
}) */
// 2. 删除多个
Student.deleteMany({ sex: '女' }).then(r => {
console.log(r);
})
Express是一个基于Node平台的web应用开发框架,它提供了一系列的强大特性,帮助你创建各种Web应用。我们可以使用 npm install express 命令进行下载。
Express框架特性:
1.提供了方便简洁的路由定义方式
2.对获取HTTP请求参数进行了简化处理
3.对模板引擎支持程度高,方便渲染动态HTML页面
4.提供了中间件机制有效控制HTTP请求
5.拥有大量第三方中间件对功能进行扩展
// 当客户端以get方式访问/时
app.get('/', (req, res) => {
// 对客户端做出响应
res.send('Hello Express');
});
// 当客户端以post方式访问/add路由时
app.post('/add', (req, res) => {
res.send('使用post方式请求了/add路由');
});
// 所有方式,优先级最高
app.all('/add',(req,res)=>{
res.send('使用get/post方式请求了/add路由');
})
app.get('/', (req, res) => {
// 获取GET参数
console.log(req.query);
});
app.post('/', (req, res) => {
// 获取POST参数
console.log(req.body);
})
使用Express框架创建web服务器及其简单,调用express模块返回的函数即可。
// 引入Express框架
const express = require('express');
// 使用框架创建web服务器
const app = express();
// 当客户端以get方式访问/路由时
app.get('/', (req, res) => {
// 对客户端做出响应 send方法会根据内容的类型自动设置请求头
res.send('Hello Express');
});
// 程序监听3000端口
app.listen(3000,()=>{console.log('服务已经启动,端口号3000')});
2.5.1 什么是中间件
中间件就是一堆方法,可以接收客户端发来的请求、可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理。中间件主要由两部分构成,中间件方法以及请求处理函数。
中间件方法由Express提供,负责拦截请求,请求处理函数由开发人员提供,负责处理请求。
app.get('请求路径', '处理函数') // 接收并处理get请求
app.post('请求路径', '处理函数') // 接收并处理post请求
可以针对同一个请求设置多个中间件,对同一个请求进行多次处理。默认情况下,请求从上到下依次匹配中间件,一旦匹配成功,终止匹配。
可以调用next方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件。
app.get('/request', (req, res, next) => {
req.name = "张三";
next();
});
app.get('/request', (req, res) => {
res.send(req.name);
});
2.5.2 app.use中间件用法
app.use 匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求。
app.use((req, res, next) => {
console.log(req.url);
next();
});
app.use 第一个参数也可以传入请求地址,代表不论什么请求方式,只要是这个请求地址就接收这个请求。
app.use('/admin', (req, res, next) => {
console.log(req.url);
next();
});
2.5.3 中间件应用
1.路由保护,客户端在访问需要登录的页面时,可以先使用中间件判断用户登录状态,用户如果未登录,则拦截请求,直接响应,禁止用户进入需要登录的页面。
2.网站维护公告,在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,网站正在维护中。
3.自定义404页面。
2.5.4 错误处理中间件
在程序执行的过程中,不可避免的会出现一些无法预料的错误,比如文件读取失败,数据库连接失败。错误处理中间件是一个集中处理错误的地方。
app.use((err, req, res, next) => {
res.status(500).send('服务器发生未知错误');
})
当程序出现错误时,调用next()方法,并且将错误信息通过参数的形式传递给next()方法,即可触发错误处理中间件。
app.get("/", (req, res, next) => {
fs.readFile("/file-does-not-exist", (err, data) => {
if (err) {
next(err);
}
});
});
2.5.5 捕获错误
在node.js中,异步API的错误信息都是通过回调函数获取的,支持Promise对象的异步API发生错误可以通过catch方法捕获。异步函数执行如果发生错误要如何捕获错误呢?
try catch 可以捕获异步函数以及其他同步代码在执行过程中发生的错误。
app.get("/", async (req, res, next) => {
try {
await User.find({name: '张三'})
} catch(ex) {
next(ex);
}
});
const express = require('express')
const home = express.Router(); // 创建路由对象
app.use('/home', home); // 将路由和请求路径进行匹配
home.get('/index', () => { // 在home路由下继续创建路由
res.send('欢迎来到博客展示页面'); // /home/index
});
const home = express.Router(); // home.js
home.get('/index', () => {
res.send('欢迎来到博客展示页面');
});
module.exports = home;
const admin = express.Router(); // admin.js
admin.get('/index', () => {
res.send('欢迎来到博客管理页面');
});
module.exports = admin;
const home = require('./route/home.js'); // app.js
const admin = require('./route/admin.js');
app.use('/home', home);
app.use('/admin', admin);
2.7.1 GET参数的获取
Express框架中使用req.query即可获取GET参数,框架内部会将GET参数转换为对象并返回。
// 接收地址栏中问号后面的参数 // 例如: http://localhost:3000/?name=zhangsan&age=30
app.get('/', (req, res) => {
console.log(req.query); // {"name": "zhangsan", "age": "30"}
});
2.7.2 POST参数的获取
旧版本的Express中接收post请求参数需要借助第三方包 body-parser。
const bodyParser = require('body-parser'); // 引入body-parser模块
app.use(bodyParser.json()); // 配置body-parser模块 // 设置允许接收json格式的数据
app.use(bodyParser.urlencoded({ extended: false })); // 设置允许接收urlencoded格式的数据
新版本的Express不需要借助第三方包 body-parser
app.use(express.json()) // 设置允许接收json格式的数据
app.use(express.urlencoded({extended:false})) // 设置允许接收urlencoded格式的数据
app.post('/add', (req, res) => { // 接收请求
// 接收请求参数
console.log(req.body);
})
2.7.3 Express路由参数
app.get('/find/:id', (req, res) => {
console.log(req.params); // {id: 123}
});
localhost:3000/find/123
通过Express内置的express.static可以方便地托管静态文件,例如img、CSS、JavaScript 文件等。app.use(express.static('public'));
现在,public 目录下面的文件就可以访问了。
1.http://localhost:3000/images/kitten.jpg
2.http://localhost:3000/css/style.css
3.http://localhost:3000/js/app.js
4.http://localhost:3000/images/bg.png
5.http://localhost:3000/hello.html
// 使用express框架开发后台服务器
// 1.引入Express框架
const express = require('express')
// 2.使用Express框架方法创建web服务器
const app = express()
// 3.开启服务器,并监听一个端口号
app.listen(8848,()=>{
console.log('服务器开启成功,端口号是8848');
})
// 使用文件系统,对数据做持久化保存
const fs = require('fs')
fs.readFile('./files/data.txt',(err,bf)=>{
//\r\n是换行符,可以简写成\n
bf.toString().split('\r\n').forEach(r=>{
let stu = {}
let arr = r.split('|')
stu.no = arr[0]
stu.name = arr[1]
stu.age = arr[2]
stu.sex = arr[3]
list.push(stu)
})
})
//定义数据
let list = []
// 4.创建接口 (路由)
//查询学生的接口
app.get('/list',(req,res)=>{
//req是请求对象
//res是响应对象
//setHeader()方法,用于设置响应头信息
//这里是设置允许跨域请求
res.setHeader('Access-Control-Allow-Origin','*')
//send()方法,用于响应结果
res.send(list)
})
//添加学生的接口
app.get('/add',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*')
//获取get请求方式的参数,所有参数会保存到一个对象中
//这里返回的是一个学生对象
let stu = req.query
//设置学生对象的学号
stu.no = list.length+1
//将学生对象添加到学生数组中
list.push(stu)
//整理写入到文件中的数据
let data = '\r\n'+stu.no+'|'+stu.name+'|'+stu.age+'|'+stu.sex
//利用文件系统,将数据添加到文件中
fs.writeFile('./files/data.txt',data,{flag:'a'},(err)=>{
if(!err)
res.send(true)
else
res.send(false)
})
})
学号
姓名
性别
年龄
姓名:
性别:
年龄:
// express框架的使用
//01.导入express框架
const express = require('express')
//02.创建服务器对象
const app = express()
//03.监听一个端口号
app.listen(8848,()=>{
console.log('服务器成功开启,端口号是8848');
})
// 设置允许接收json格式的数据
app.use(express.json())
// 设置允许接收urlencoded格式的数据
app.use(express.urlencoded({extended:false}))
//定义请求中间件,所有的请求会先由中间件拦截,验证完权限后,再放行
app.use((req,res,next)=>{
//设置允许跨域
res.setHeader('Access-Control-Allow-Origin','*')
//设置允许加请求头信息
res.setHeader('Access-Control-Allow-Headers','*')
//必须调用了next()方法后,才会继续往后执行
next()
})
//导出app对象
exports.app = app
// 操作数据库
// 01.导入mongoose库
const mongoose = require('mongoose')
// 02.打开数据库连接
mongoose.connect('mongodb://localhost/myschool').then(()=>{
console.log('myschool数据库连接成功');
})
// 03.创建student表规范
const studentSchema = new mongoose.Schema({
name:String,
sex:String,
age:Number,
hobbies:Array,
email:String,
isVIP:Boolean
})
// 04.创建student表对象
const Student = mongoose.model('student',studentSchema)
//导出学生表对象
exports.Student = Student
// 导入服务器对象
const {app} = require('./app.js')
// 导入Student表对象
const {Student} = require('./db.js')
// 查询学生信息
app.get('/list',(req,res)=>{
//获取参数name
let {name} = req.query
Student.find({name:{
//正则表达式匹配姓名模糊查询
$regex:new RegExp(`${name}`,'g')
}}).then(r=>{
res.send(r)
})
})
// 添加学生信息
app.post('/add',(req,res)=>{
Student.create(req.body).then(r=>{
res.send(true)
}).catch(err=>{
res.send(false)
})
})
// 删除学生信息
app.post('/delete',(req,res)=>{
let {_id} = req.body
Student.deleteOne({_id}).then(r=>{
res.send(true)
}).catch(err=>{
res.send(false)
})
})
//根据id返回一个学生信息
app.get('/getOne',(req,res)=>{
let {_id} = req.query
Student.findOne({_id}).then(r=>{
res.send(r)
})
})
// 根据id修改指定的学生信息
app.post('/update',(req,res)=>{
let {_id} = req.body
Student.updateOne({_id},req.body).then(r=>{
res.send(true)
}).catch(err=>{
res.send(false)
})
})
HTTP (hypertext transport protocol) 协议 [超文本传输协议],协议详细规定了浏览器和万维网之间相互通信的规则。
3.1.1 请求
重点是格式与参数,
行 类型(GET POST) / URL / HTTP/1.1
头 Host: baidu.com
Cookie: name=汽车
Content-type: application/x-www-form-urlencoded
User-Agent: chrome 83
空行
体 username=admin&password=admin
3.1.2 响应
行 HTTP/1.1 (200/404/403/401/500) OK
头 Content-type: text/html;charset=utf-8
Content-length: 2048
Content-encoding: gzip
空行
体
Ajax
同源策略:是浏览器的一种安全策略。同源:协议、域名、端口号 必须完全相同。违背同源策略就是跨域。那么如何解决跨域:
1.JSONP:是一个非官方的跨域解决方案,只支持get请求。JSONP 就是利用script标签的跨域能力来发送请求的。比如:img link iframe script。
2.CORS:跨域资源共享。是官方的跨域解决方案。新增了一组HTTP首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
//设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*');
//响应头 *表示所有类型的头信息都可以接受
response.setHeader('Access-Control-Allow-Headers','*');
3.3.1 GET 请求
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化 设置请求方法和URL
xhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');
//3. 发送
xhr.send();
//4. 事件绑定 处理服务端返回的结果
// on when 当....时候
// readystate 是 xhr 对象中的属性,表示状态 0 1 2 3 4
// 0 表示未初始化
// 1 表示open方法已经调用完毕
// 2 表示send方法已经调用完毕
// 3 表示服务端返回了部分的结果
// 4 表示服务端返回了所有结果
// change 改变
xhr.onreadystatechange = function(){
//判断(服务端返回了所有结果)
if(xhr.readyState === 4){
//判断响应状态码 200 404 403 401 500
//2xx 成功
if(xhr.status >= 200 && xhr.status < 300){
//处理结果 行 头 空行 体
//1. 响应行
console.log(xhr.status); //状态码
console.log(xhr.statusText); //状态字符串
console.log(xhr.getAllResponseHeaders()); //所有响应头
console.log(xhr.response); //响应体
//设置 result 的文本
result.innerHTML = xhr.response
}else{
}
}
}
3.3.2 POST 请求
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化 设置类型与 URL
xhr.open('POST','http://127.0.0.1:8000/server')
//设置请求头
//Content-Type 是设置请求体内容的类型
//application/x-www.form-urlencoded 是参数查询字符串的类型
//application/json 是json格式类型
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
//自定义头
xhr.setRequestHeader('name','张三')
//3. 发送
xhr.send('a=100&b=200&c=300')
// xhr.send('a:100&b:200&c:300')
//4. 事件绑定
xhr.onreadystatechange = function(){
//对状态判断
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
//处理服务端返回的结果
result.innerHTML = xhr.response
}
}
}
//加载学生的方法
function loadStudent(name = '') {
let xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost:8848/list?name=' + name)
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
document.querySelector('#tbody').innerHTML = template('list', JSON.parse(xhr.responseText))
}
}
}
}
//调用加载学生信息的方法
loadStudent()
//搜索按钮点事件
document.querySelector('#search').onclick = function () {
//重新调用加载学生信息的方法
loadStudent(document.querySelector('#name').value)
}
//添加按钮点击事件
document.querySelector('#add').onclick = function () {
//获取用户输入的信息
let name = document.querySelector('#name2').value
let sex = '男'
if (document.querySelector('#nv').checked) {
sex = '女'
}
let age = document.querySelector('#age').value
let hobbies = []
document.getElementsByName('hobbies').forEach(r => {
if (r.checked) {
hobbies.push(r.value)
}
})
let email = document.querySelector('#email').value
let isVIP = document.querySelector('#isVIP').checked
//根据获取到的信息,创建一个学生对象
let stu = {
name, sex, age, hobbies, email, isVIP
}
//定义请求的地址
let url = 'http://localhost:8848/add'
if(document.querySelector('#add').innerHTML=='修改'){
//切换成修改接口地址
url = 'http://localhost:8848/update'
//设置学生对象的_id属性
stu._id = document.querySelector('#_id').value
}
let xhr = new XMLHttpRequest()
xhr.open('POST', url)
//通过请求头设置post请求体的格式是json
xhr.setRequestHeader('content-type', 'application/json')
xhr.send(JSON.stringify(stu))
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (JSON.parse(xhr.responseText)) {
if(document.querySelector('#add').innerHTML=="添加"){
alert('添加成功')
}else{
alert('修改成功')
document.querySelector('#add').innerHTML = '添加'
}
//调用加载学生信息的方法
loadStudent()
//清空表单
clearInput()
}
}
}
}
}
//删除方法
function del(_id) {
if (!confirm('确定删除吗?')) return
let xhr = new XMLHttpRequest()
xhr.open('POST', 'http://localhost:8848/delete')
//通过请求头设置post请求体的格式是json
xhr.setRequestHeader('content-type', 'application/json')
xhr.send(JSON.stringify({ _id }))
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (JSON.parse(xhr.responseText)) {
alert('删除成功')
//调用加载学生信息的方法
loadStudent()
}
}
}
}
}
//根据id获取学生信息
function getOne(_id) {
let xhr = new XMLHttpRequest()
xhr.open('GET', 'http://localhost:8848/getOne?_id=' + _id)
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let stu = JSON.parse(xhr.responseText)
document.querySelector('#name2').value = stu.name
if(stu.sex=='男'){
document.querySelector('#nan').checked = true
}else{
document.querySelector('#nv').checked = true
}
document.querySelector('#age').value = stu.age
//爱好
stu.hobbies.forEach(h=>{
document.querySelector(`input[value='${h}']`).checked = true
})
document.querySelector('#email').value = stu.email
document.querySelector('#isVIP').checked = stu.isVIP
//将_id在隐藏域里面保存起来
document.querySelector('#_id').value = stu._id
}
}
}
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '修改'
}
//取消按钮点击事件
document.querySelector('#cancel').onclick = function(){
//清空表单元素
clearInput()
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '添加'
}
//清空表单方法
function clearInput() {
document.querySelector('#name2').value = ""
document.querySelector('#nan').checked = true
document.querySelector('#age').value = ""
document.getElementsByName('hobbies').forEach(r => {
r.checked = false
})
document.querySelector('#email').value = ""
document.querySelector('#isVIP').checked = false
}
3.3.3 响应 JSON
//发送请求
const xhr = new XMLHttpRequest();
//设置响应体数据的类型
xhr.responseType = 'json';
//初始化
xhr.open('GET','http://127.0.0.1:8000/json-server');
//发送
xhr.send()
//事件绑定
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >=200 && xhr.status<300){
// result.innerHTML = xhr.response
//手动对数据转换
// let data = JSON.parse(xhr.response)
// console.log(data);
// result.innerHTML = data.name
//自动转换-->设置响应体数据的类型
// console.log(xhr.response);
result.innerHTML = xhr.response.name
}
}
}
3.3.4 IE缓存问题
const xhr = new XMLHttpRequest();
// url添加时间戳
xhr.open('GET','http://127.0.0.1:8000/ie?t='+Date.now());
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response
}
}
}
3.3.5 请求超时与网络异常
const xhr = new XMLHttpRequest();
//超时设置 2s 设置
xhr.timeout = 2000
//超时回调
xhr.ontimeout = function(){
alert('网络异常,请稍后重试!')
}
//网络异常回调
xhr.onerror = function(){
alert('你的网络似乎出了一些问题!')
}
xhr.open('GET','http://127.0.0.1:8000/delay');
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
result.innerHTML = xhr.response
}
}
}
3.3.6 取消请求
let xhr = new XMLHttpRequest();
xhr.open('GET','http://127.0.0.1:8000/delay');
//发送请求
xhr.send()
//取消请求
xhr.abort()
3.3.7 重复发送请求问题
//判断标识变量
if(isSending) x.abort(); //如果正在发送,则取消该请求,创建一个新的请求
x = new XMLHttpRequest();
//修改 标识变量的值
isSending = true
x.open('GET', 'http://127.0.0.1:8000/delay');
x.send()
x.onreadystatechange = function(){
if(x.readyState === 4){
//修改标识变量
isSending = false
}
}
3.4.1 GET方式
// 第四个参数:设置json。表示响应体是json对象
// 第四个参数:不设置。默认响应体是字符串
$.get('http://127.0.0.1:8000/jquery-server',{a:100,b:200},function(data){
console.log(data);
},'json')
3.4.2 POST方式
$.post('http://127.0.0.1:8000/jquery-server',{a:100,b:200},function(data){
console.log(data);
})
3.4.3 通用型方法ajax
$.ajax({
//url
url:'http://127.0.0.1:8000/jquery-server',
//参数
data:{a:100,b:200},
//请求类型
type:'GET',
//响应体结果
dataType:'json',
//成功的回调
success:function(data){
console.log(data);
},
//超时时间
timeout:2000,
//失败的回调
error:function(){
console.log('出错啦!');
},
//头信息
headers:{
c:300,
d:400
}
})
//加载学生的方法
function loadStudent(name = '') {
$.get('http://localhost:8848/list', {
name
}, r => {
document.querySelector('#tbody').innerHTML = template('list', r)
})
}
//调用加载学生信息的方法
loadStudent()
//搜索按钮点事件
document.querySelector('#search').onclick = function () {
//重新调用加载学生信息的方法
loadStudent(document.querySelector('#name').value)
}
//添加按钮点击事件
document.querySelector('#add').onclick = function () {
//获取用户输入的信息
let name = document.querySelector('#name2').value
let sex = '男'
if (document.querySelector('#nv').checked) {
sex = '女'
}
let age = document.querySelector('#age').value
let hobbies = []
document.getElementsByName('hobbies').forEach(r => {
if (r.checked) {
hobbies.push(r.value)
}
})
let email = document.querySelector('#email').value
let isVIP = document.querySelector('#isVIP').checked
//根据获取到的信息,创建一个学生对象
let stu = {
name, sex, age, hobbies, email, isVIP
}
//定义请求的地址
let url = 'http://localhost:8848/add'
if (document.querySelector('#add').innerHTML == '修改') {
//切换成修改接口地址
url = 'http://localhost:8848/update'
//设置学生对象的_id属性
stu._id = document.querySelector('#_id').value
}
//注意:这里添加和修改操作,采用的是jquery的统一ajax方法,因为要做特殊处理
$.ajax({
url,
type: 'POST',
data: stu,
dataType: 'json',
// 这里需要采用传统的方式来序列化数据,jquery默认会将对象的对象属性拆分开了序列化
traditional: true,
success: r => {
if (r) {
if (document.querySelector('#add').innerHTML == "添加") {
alert('添加成功')
} else {
alert('修改成功')
document.querySelector('#add').innerHTML = '添加'
}
//调用加载学生信息的方法
loadStudent()
//清空表单
clearInput()
}
}
})
}
//删除方法
function del(_id) {
if (!confirm('确定删除吗?')) return
$.post('http://localhost:8848/delete', { _id }, r => {
if (r) {
alert('删除成功')
//调用加载学生信息的方法
loadStudent()
}
})
}
//根据id获取学生信息
function getOne(_id) {
let xhr = new XMLHttpRequest()
$.get('http://localhost:8848/getOne', { _id }, stu => {
document.querySelector('#name2').value = stu.name
if (stu.sex == '男') {
document.querySelector('#nan').checked = true
} else {
document.querySelector('#nv').checked = true
}
document.querySelector('#age').value = stu.age
//爱好
stu.hobbies.forEach(h => {
document.querySelector(`input[value='${h}']`).checked = true
})
document.querySelector('#email').value = stu.email
document.querySelector('#isVIP').checked = stu.isVIP
//将_id在隐藏域里面保存起来
document.querySelector('#_id').value = stu._id
})
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '修改'
}
//取消按钮点击事件
document.querySelector('#cancel').onclick = function () {
//清空表单元素
clearInput()
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '添加'
}
//清空表单方法
function clearInput() {
document.querySelector('#name2').value = ""
document.querySelector('#nan').checked = true
document.querySelector('#age').value = ""
document.getElementsByName('hobbies').forEach(r => {
r.checked = false
})
document.querySelector('#email').value = ""
document.querySelector('#isVIP').checked = false
}
3.5.1 GET方式
axios.get('/axios-server',{
//url 参数
params:{
id:100,
vip:7
},
//请求头信息
headers:{
name:'张三',
age:20
}
}).then(value=>{
console.log(value);
})
3.5.2 POST方式
axios.post('/axios-server',{
//请求体
{
username:'admin',
password:'admin'
},
{
//url 参数
params:{
id:200,
vip:9
},
//请求头参数
headers:{
height:180,
weight:180
}
}).then(value=>{
console.log(value);
})
3.5.3 通用方式
axios({
//请求方法
method: 'POST',
//url
url:'/axios-server',
//url参数
params:{
vip:10,
level:30
},
//头信息
headers:{
a:100,
b:200
},
//请求体参数
data:{
username:'admin',
password:'admin'
}
}).then(response=>{
console.log(response);
//响应状态码
console.log(response.status);
//响应状态字符串
console.log(response.statusText);
//响应头信息
console.log(response.headers);
//响应体
console.log(response.data);
})
//加载学生的方法
/* function loadStudent(name = '') {
//get方法(),第一个参数是请求地址,第二个参数对象设置请求参数
//注意:请求参数要放置在第二个参数对象的params属性中
axios.get('http://localhost:8848/list', {
params: {
name
}
}).then(({ data }) => {
document.querySelector('#tbody').innerHTML = template('list', data)
})
} */
async function loadStudent(name = '') {
//async 配合 await,简化了.then返回结果的过程
let {data} = await axios.get('http://localhost:8848/list', {
params: {
name
}
})
document.querySelector('#tbody').innerHTML = template('list', data)
}
//调用加载学生信息的方法
loadStudent()
//搜索按钮点事件
document.querySelector('#search').onclick = function () {
//重新调用加载学生信息的方法
loadStudent(document.querySelector('#name').value)
}
//添加按钮点击事件
document.querySelector('#add').onclick = function () {
//获取用户输入的信息
let name = document.querySelector('#name2').value
let sex = '男'
if (document.querySelector('#nv').checked) {
sex = '女'
}
let age = document.querySelector('#age').value
let hobbies = []
document.getElementsByName('hobbies').forEach(r => {
if (r.checked) {
hobbies.push(r.value)
}
})
let email = document.querySelector('#email').value
let isVIP = document.querySelector('#isVIP').checked
//根据获取到的信息,创建一个学生对象
let stu = {
name, sex, age, hobbies, email, isVIP
}
//定义请求的地址
let url = 'http://localhost:8848/add'
if (document.querySelector('#add').innerHTML == '修改') {
//切换成修改接口地址
url = 'http://localhost:8848/update'
//设置学生对象的_id属性
stu._id = document.querySelector('#_id').value
}
axios.post(url, stu).then(({ data }) => {
if (data) {
if (document.querySelector('#add').innerHTML == "添加") {
alert('添加成功')
} else {
alert('修改成功')
document.querySelector('#add').innerHTML = '添加'
}
//调用加载学生信息的方法
loadStudent()
//清空表单
clearInput()
}
})
}
//删除方法
function del(_id) {
if (!confirm('确定删除吗?')) return
axios.post('http://localhost:8848/delete', { _id }).then(({ data }) => {
if (data) {
alert('删除成功')
//调用加载学生信息的方法
loadStudent()
}
})
}
//根据id获取学生信息
function getOne(_id) {
axios.get('http://localhost:8848/getOne', {
params: {
_id
}
}).then(({data:stu}) => {
document.querySelector('#name2').value = stu.name
if (stu.sex == '男') {
document.querySelector('#nan').checked = true
} else {
document.querySelector('#nv').checked = true
}
document.querySelector('#age').value = stu.age
//爱好
stu.hobbies.forEach(h => {
document.querySelector(`input[value='${h}']`).checked = true
})
document.querySelector('#email').value = stu.email
document.querySelector('#isVIP').checked = stu.isVIP
//将_id在隐藏域里面保存起来
document.querySelector('#_id').value = stu._id
})
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '修改'
}
//取消按钮点击事件
document.querySelector('#cancel').onclick = function () {
//清空表单元素
clearInput()
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '添加'
}
//清空表单方法
function clearInput() {
document.querySelector('#name2').value = ""
document.querySelector('#nan').checked = true
document.querySelector('#age').value = ""
document.getElementsByName('hobbies').forEach(r => {
r.checked = false
})
document.querySelector('#email').value = ""
document.querySelector('#isVIP').checked = false
}
fetch('http://127.0.0.1:8000/fetch-server?vip=10',{
//请求方法
method:'POST',
//请求头
headers:{
name:'bing'
},
//请求体
body:'username=admin&password=admin'
}).then(response=>{
// console.log(response);
// return response.text()
return response.json()
}).then(response=>{
console.log(response);
})
//加载学生的方法
function loadStudent(name = '') {
//fetch()方法,用于发送请求,返回结果是响应对象
fetch('http://localhost:8848/list?name=' + name).then(res => {
//响应对象的json()方法,返回请求的结果
return res.json()
}).then(r => {
document.querySelector('#tbody').innerHTML = template('list', r)
})
}
//调用加载学生信息的方法
loadStudent()
//搜索按钮点事件
document.querySelector('#search').onclick = function () {
//重新调用加载学生信息的方法
loadStudent(document.querySelector('#name').value)
}
//添加按钮点击事件
document.querySelector('#add').onclick = function () {
//获取用户输入的信息
let name = document.querySelector('#name2').value
let sex = '男'
if (document.querySelector('#nv').checked) {
sex = '女'
}
let age = document.querySelector('#age').value
let hobbies = []
document.getElementsByName('hobbies').forEach(r => {
if (r.checked) {
hobbies.push(r.value)
}
})
let email = document.querySelector('#email').value
let isVIP = document.querySelector('#isVIP').checked
//根据获取到的信息,创建一个学生对象
let stu = {
name, sex, age, hobbies, email, isVIP
}
//定义请求的地址
let url = 'http://localhost:8848/add'
if (document.querySelector('#add').innerHTML == '修改') {
//切换成修改接口地址
url = 'http://localhost:8848/update'
//设置学生对象的_id属性
stu._id = document.querySelector('#_id').value
}
//fetch()方法的第一个参数是请求地址
//第二个参数是配置对象
fetch(url, {
//请求方式是POST
method: 'POST',
//设置请求头信息
headers: {
'Content-Type': 'application/json',
},
//设置post请求方式的请求体,其实就是post请求参数
body: JSON.stringify(stu)
}).then(res => {
return res.json()
}).then(r => {
if (r) {
if (document.querySelector('#add').innerHTML == "添加") {
alert('添加成功')
} else {
alert('修改成功')
document.querySelector('#add').innerHTML = '添加'
}
//调用加载学生信息的方法
loadStudent()
//清空表单
clearInput()
}
})
}
//删除方法
function del(_id) {
if (!confirm('确定删除吗?')) return
fetch('http://localhost:8848/delete', {
//请求方式是POST
method: 'POST',
//设置请求头信息
headers: {
'Content-Type': 'application/json',
},
//设置post请求方式的请求体,其实就是post请求参数
body: JSON.stringify({ _id })
}).then(res => {
return res.json()
}).then(r => {
if (r) {
alert('删除成功')
//调用加载学生信息的方法
loadStudent()
}
})
}
//根据id获取学生信息
function getOne(_id) {
fetch('http://localhost:8848/getOne?_id=' + _id).then(res => {
return res.json()
}).then(stu => {
document.querySelector('#name2').value = stu.name
if (stu.sex == '男') {
document.querySelector('#nan').checked = true
} else {
document.querySelector('#nv').checked = true
}
document.querySelector('#age').value = stu.age
//爱好
stu.hobbies.forEach(h => {
document.querySelector(`input[value='${h}']`).checked = true
})
document.querySelector('#email').value = stu.email
document.querySelector('#isVIP').checked = stu.isVIP
//将_id在隐藏域里面保存起来
document.querySelector('#_id').value = stu._id
})
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '修改'
}
//取消按钮点击事件
document.querySelector('#cancel').onclick = function () {
//清空表单元素
clearInput()
//修改添加按钮的文本
document.querySelector('#add').innerHTML = '添加'
}
//清空表单方法
function clearInput() {
document.querySelector('#name2').value = ""
document.querySelector('#nan').checked = true
document.querySelector('#age').value = ""
document.getElementsByName('hobbies').forEach(r => {
r.checked = false
})
document.querySelector('#email').value = ""
document.querySelector('#isVIP').checked = false
}