AJAX的优势
AJAX的运行原理和步骤
一般情况下不会返回一个文本,而是JSON对象作为响应,但是服务器端一般是字符串所以要转换为对象
转换加字符拼接
传递get请求参数,参数要自己拼接
post 请求如何传递请求参数
引入body-parser和app.use 模块
还可以用JSON格式来传递(请求参数格式
get不能传JSON 然后传统网站表单也不可以用
06-获取服务器端响应数据的另一种方式
AJAX状态码
// 当ajax状态码发生变化的时候出发
xhr.onreadystatechange = function()
有点过时,但需要了解
07.Ajax错误处理
利用xhr.status()来返回HTTP状态码
AJAX在低版本的IE中存在缓存的问题,后一次改变了数据依然会加载读取前一次数据的缓存,所以通过改变每次地址,使每次地址都不同来解决这个问题
AJAX是异步代码
false代表同步。应该去掉代表异步
AJAX的封装
基本配置
将函数抛出去,通过用户每次调用来实现
通过success方法来实现
拼接字符串
多了个&
利用循环来拼接字符,get和post输出的地址不同,进行区分
调用get方法地址正确
在post请求中分辨是不是json的格式传递
做判断和试图用JSON
先设置POST路由
添加header来确认
查看内容类型
是字符串类型
对状态码的成功和失败情况进行分别处理
得到结果
完成状态码的修改
对于json类型的数据要转换为对象类型,完成这一封装,比较好调用
以上完成对于JSON的封装
设定一个默认值
如果参数没有调用就使用默认值,如果调用就覆盖默认值
结果没变 同样没有调用的参数数据采用默认值
到此AJAX的封装结束!
使用模板引擎提供的模板语法将数据与HTML进行拼接
以上完成
案例:验证邮箱地址是否输入正确
对于info的id进行设置 如果正确为bg-sucess
错误为bg-danger
先判断输入的邮箱是否符合规则
若符合规则,则调用AJAX将参数带入
然后传递到服务器端APP.JS
APP.JS进行判断,并传回信息到SUCCESS和 ERROR中去
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证邮箱地址是否已经注册</title>
<link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css">
<style type="text/css">
p:not(:empty) {
padding: 15px;
}
.container {
padding-top: 100px;
}
</style>
</head>
<body>
<div class="container">
<div class="form-group">
<label>邮箱地址</label>
<input type="email" class="form-control" placeholder="请输入邮箱地址" id="email">
</div>
<!-- 错误 bg-danger 正确 bg-success -->
<p id="info"></p>
</div>
<script src="/js/ajax.js"></script>
<script>
// 获取页面中的元素
var emailInp = document.getElementById('email');
var info = document.getElementById('info');
// 当文本框离开焦点以后
emailInp.onblur = function () {
// 获取用户输入的邮箱地址
var email = this.value;
// 验证邮箱地址的正则表达式
var reg = /^[A-Za-z\d]+([-_.][A-Za-z\d]+)*@([A-Za-z\d]+[-.])+[A-Za-z\d]{2,4}$/;
// 如果用户输入的邮箱地址不符合规则
if (!reg.test(email)) {
// 给出用户提示
info.innerHTML = '请输入符合规则的邮箱地址';
// 让提示信息显示为错误提示信息的样式
info.className = 'bg-danger';
// 阻止程序向下执行
return;
}
// 向服务器端发送请求
ajax({
type: 'get',
url: 'http://localhost:3000/verifyEmailAdress',
data: {
email: email
},
success: function (result) {
console.log(result);
info.innerHTML = result.message;
info.className = 'bg-success';
},
error: function (result) {
console.log(result)
info.innerHTML = result.message;
info.className = 'bg-danger';
}
});
}
</script>
</body>
</html>
案例:搜索框输入自动提示
通过AJAX向服务器传递数据
通过template来拼接数据和html
利用循环将获取的数据呈列表显示
result中key就是输入的内容,如果包含key的将result返回拼接在列表中
用户每次输入都会向服务器传递一次,我们用延时器来取消掉这种操作,设置在八秒传送一次,用户每次输入都将延时器取消掉,这样只有在输入完成之后没有输入后的八秒才会向服务器发送请求
同时利用trim来检测用户是否输入了内容,若没有输入内容,将下拉提示框隐藏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>搜索框输入文字自动提示</title>
<link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css">
<style type="text/css">
.container {
padding-top: 150px;
}
.list-group {
display: none;
}
</style>
</head>
<body>
<div class="container">
<div class="form-group">
<input type="text" class="form-control" placeholder="请输入搜索关键字" id="search">
<ul class="list-group" id="list-box">
</ul>
</div>
</div>
<script src="/js/ajax.js"></script>
<script src="/js/template-web.js"></script>
<script type="text/html" id="tpl">
{{each result}}
<li class="list-group-item">{{$value}}</li>
{{/each}}
</script>
<script>
// 获取搜索框
var searchInp = document.getElementById('search');
// 获取提示文字的存放容器
var listBox = document.getElementById('list-box');
// 存储定时器的变量
var timer = null;
// 当用户在文本框中输入的时候触发
searchInp.oninput = function () {
// 清除上一次开启的定时器
clearTimeout(timer);
// 获取用户输入的内容
var key = this.value;
// 如果用户没有在搜索框中输入内容
if (key.trim().length == 0) {
// 将提示下拉框隐藏掉
listBox.style.display = 'none';
// 阻止程序向下执行
return;
}
// 开启定时器 让请求延迟发送
timer = setTimeout(function () {
// 向服务器端发送请求
// 向服务器端索取和用户输入关键字相关的内容
ajax({
type: 'get',
url: 'http://localhost:3000/searchAutoPrompt',
data: {
key: key
},
success: function (result) {
// 使用模板引擎拼接字符串
var html = template('tpl', {result: result});
// 将拼接好的字符串显示在页面中
listBox.innerHTML = html;
// 显示ul容器
listBox.style.display = 'block';
}
})
}, 800)
}
</script>
</body>
</html>
完成!
案例:省市区三级联动
通过each循环和template拼接获得列表
onchange事件获得对应省id
获取对应市的列表
选择市后,同样方法获得区列表
当改变省ID时,将区制空
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>搜索框输入文字自动提示</title>
<link rel="stylesheet" href="/assets/bootstrap/dist/css/bootstrap.min.css">
<style type="text/css">
.container {
padding-top: 150px;
}
</style>
</head>
<body>
<div class="container">
<div class="form-inline">
<div class="form-group">
<select class="form-control" id="province"></select>
</div>
<div class="form-group">
<select class="form-control" id="city">
<option>请选择城市</option>
</select>
</div>
<div class="form-group">
<select class="form-control" id="area">
<option>请选择县城</option>
</select>
</div>
</div>
</div>
<script src="/js/ajax.js"></script>
<script src="/js/template-web.js"></script>
<!-- 省份模板 -->
<script type="text/html" id="provinceTpl">
<option>请选择省份</option>
{{each province}}
<option value="{{$value.id}}">{{$value.name}}</option>
{{/each}}
</script>
<!-- 城市模板 -->
<script type="text/html" id="cityTpl">
<option>请选择城市</option>
{{each city}}
<option value="{{$value.id}}">{{$value.name}}</option>
{{/each}}
</script>
<!-- 县城模板 -->
<script type="text/html" id="areaTpl">
<option>请选择县城</option>
{{each area}}
<option value="{{$value.id}}">{{$value.name}}</option>
{{/each}}
</script>
<script>
// 获取省市区下拉框元素
var province = document.getElementById('province');
var city = document.getElementById('city');
var area = document.getElementById('area');
// 获取省份信息
ajax({
type: 'get',
url: 'http://localhost:3000/province',
success: function (data) {
// 将服务器端返回的数据和html进行拼接
var html = template('provinceTpl', {province: data});
// 将拼接好的html字符串显示在页面中
province.innerHTML = html;
}
});
// 为省份的下拉框添加值改变事件
province.onchange = function () {
// 获取省份id
var pid = this.value;
// 清空县城下拉框中的数据
var html = template('areaTpl', {area: []});
area.innerHTML = html;
// 根据省份id获取城市信息
ajax({
type: 'get',
url: '/cities',
data: {
id: pid
},
success: function (data) {
var html = template('cityTpl', {city: data});
city.innerHTML = html;
}
})
};
// 当用户选择城市的时候
city.onchange = function () {
// 获取城市id
var cid = this.value;
// 根据城市id获取县城信息
ajax({
type: 'get',
url: 'http://localhost:3000/areas',
data: {
id: cid
},
success: function(data) {
var html = template('areaTpl', {area: data});
area.innerHTML = html;
}
})
}
</script>
</body>
</html>
完成!
利用formdate也可以在客户端获取html,转换为表单的样式,不必拼接。
formdate对象的使用方法
formdate不能用get方式,只能是post方式,body-parser不能用,用的是formidable
.on('click', function() {
$.ajax({
// 请求方式
type: 'get',
// 请求地址
url: '/base',
// 请求成功以后函数被调用
success: function(response) {
// response为服务器端返回的数据
// 方法内部会自动将json字符串转换为json对象
console.log(response);
},
// 请求失败以后函数被调用
error: function(xhr) {
console.log(xhr)
}
})
});
</script>
</body>
</html>
// 请求方式
type: 'post',
app.get('/base', (req, res) => {
res.send({
name: 'zhangsan',
age: 30
})
});
app.post('/base', (req, res) => {
res.status(400).send({
name: 'zhaoliu',
age: 35
})
});
error排出
完成
02.$.ajax方法传递请求参数 03.beforeSend方法的说明
$AJAX会自动把客户端的请求参数由对象转换成字符串型的,对于JSON字符串则要进行string转换
beforesend是在请求发送前发送的
注:请求方式为post
对于JSON数据类型
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$.ajax方法基本使用</title>
</head>
<body>
<button id="btn">发送请求</button>
<script src="/js/jquery.min.js"></script>
<script>
var params = {
name: 'wangwu',
age: 300
}
$('#btn').on('click', function() {
$.ajax({
// 请求方式
type: 'post',
// 请求地址
url: '/user',
// 向服务器端发送的请求参数
//data: 'name = zhangsan & age = 100',
//data: {
// name: 'zhangsan',
// age: 100
//},
data: JSON.stringify(params),
// 指定参数的格式类型
contentType: 'application/json',
// 请求成功以后函数被调用
success: function(response) {
// response为服务器端返回的数据
// 方法内部会自动将json字符串转换为json对象
console.log(response);
}
})
});
</script>
</body>
</html>
对于beforesend
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$.ajax方法基本使用</title>
</head>
<body>
<button id="btn">发送请求</button>
<script src="/js/jquery.min.js"></script>
<script>
$('#btn').on('click', function() {
$.ajax({
// 请求方式
type: 'post',
// 请求地址
url: '/user',
// 在请求发送之前调用
beforeSend: function() {
alert('请求不会被发送')
// 请求不会被发送
return false;
},
// 请求成功以后函数被调用
success: function(response) {
// response为服务器端返回的数据
// 方法内部会自动将json字符串转换为json对象
console.log(response);
}
})
});
</script>
</body>
</html>
以上完成
04.serialize方法说明
formdate是只在HTML5中有用,jQuery用serialize方法也可以转换为字符串
将表单中用户输入的内容转换为对象类型
优化,通过循环
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>serialize方法说明</title>
</head>
<body>
<form id="form">
<input type="text" name="username">
<input type="password" name="password">
<input type="submit" value="提交">
</form>
<script src="/js/jquery.min.js"></script>
<script type="text/javascript">
$('#form').on('submit', function() {
// 将表单内容拼接成字符串类型的参数
//var params = $('#form').serialize();
//console.log(params)
serializeObject($(this));
return false;
});
// 将表单中用户输入的内容转换为对象类型
function serializeObject(obj) {
// 处理结果对象
var result = {};
// [{name: 'username', value: '用户输入的内容'}, {name: 'password', value: '123456'}]
var params = obj.serializeArray();
//console.log(params);
// 循环数组 将数组转换为对象类型
$.each(params, function(index, value) {
result[value.name] = value.value;
})
//console.log(result);
// 将处理的结果返回到函数外部
return result;
}
</script>
</body>
</html>
05.$.ajax方法发送jsonp请求
callback改名
把success返回改了
全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$.ajax方法基本使用</title>
</head>
<body>
<button id="btn">发送请求</button>
<script src="/js/jquery.min.js"></script>
<script>
function fn(response) {
console.log(response)
}
$('#btn').on('click', function() {
$.ajax({
url: '/jsonp',
// 向服务器端传递函数名字的参数名称
jsonp: 'cb',
jsonpCallback: 'fn',
// 代表现在要发送的是jsonp请求
dataType: 'jsonp'
/*,
success: function(response) {
console.log(response)
}*/
})
});
</script>
</body>
</html>
app.get('/jsonp', (req, res) => {
const cb = req.query.cb
const data = cb + "({name: 'zhaoliu'})"
res.send(data);
//res.jsonp({
// name: 'lisi',
// age: 50
})
//});
完成
g
e
t
和
get和
get和post的使用方法
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$.ajax方法基本使用</title>
</head>
<body>
<button id="btn">发送请求</button>
<script src="/js/jquery.min.js"></script>
<script>
$('#btn').on('click', function() {
//$.get('/base', 'name=zhangsan&age=30', function(response) {
// console.log(response)
//})
$.post('/base', function(response) {
console.log(response)
})
});
</script>
</body>
</html>
完成
案例:Todolist 使用AJAX
以上完成
引入
<script src="/js/jquery.min.js"></script>
<script src="/js/template-web.js"></script>
<script type="text/javascript">
</script>
<script type="text/javascript">
//用于存放任务列表的数组
var taskAry = [];
$.ajax({
url: '/todo/task',
type: 'get',
success: function(response) {
console.log(response);
}
})
</script>
将这些值进行循环输出,并展示在页面上
<script type="text/html" id="taskTpl">
{{each tasks}}
<li>
<div class="view">
<input class="toggle" type="checkbox">
<label>{{$value.title}}</label>
<button class="destroy"></button>
</div>
<input class="edit">
</li>
{{/each}}
对ul添加标签
<ul class="todo-list" id="todo-list">
</ul>
// 选择任务列表容器
var taskBox = $('#todo-list');
$.ajax({
url: '/todo/task',
type: 'get',
success: function(response) {
//console.log(response);
// 将已存在的任务存储在taskAry变量中
taskAry = response;
// 字符串拼接
var html = template('taskTpl', {
tasks: taskAry
});
// 将拼接好的字符串显示在ul标签中
taskBox.html(html);
}
})
完成
<input type="text" class="new-todo" placeholder="What needs to be done?" autofocus id="task">
获取回车键的键盘码
// 获取文本框并且添加键盘抬起事件
$('#task').on('keyup', function(event) {
console.log(event.keyCode);
})
判断用户是否在文本框中输入了任务名称
// 如果用户敲击的是回车键
if (event.keyCode == 13) {
// 判断用户是否在文本框中输入了任务名称
var taskName = $(this).val();
// 如果用户没有在文本框中输入内容
if (taskName.trim().length == 0) {
alert('请输入任务名称')
// 阻止代码向下执行
return;
}
// 向服务器端发送请求 添加任务
$.ajax({
type: 'post',
url: '/todo/addTask',
contentType: 'application/json',
data: JSON.stringify({
title: taskName
}),
success: function(response) {
console.log(response)
}
})
}
});
将任务添加到任务列表中,将拼接好的字符串显示在ul标签中
$.ajax({
type: 'post',
url: '/todo/addTask',
contentType: 'application/json',
data: JSON.stringify({
title: taskName
}),
success: function(response) {
// console.log(response)
// 将任务添加到任务列表中
taskAry.push(response);
// 字符串拼接
var html = template('taskTpl', {
tasks: taskAry
});
// 将拼接好的字符串显示在ul标签中
taskBox.html(html);
}
})
}
});
添加成功后,文本框里的输入自动删除
// 添加任务的文本框
var taskInp = $('#task');
// 获取文本框并且添加键盘抬起事件
taskInp.on('keyup', function(event) {
// 清空文本框中的内容
taskInp.val('');
对于字符串的拼接与显示,两个AJAX中是重复的,所以可以封装成render
// 拼接字符串 将拼接好的字符串显示在页面中
function render() {
// 字符串拼接
var html = template('taskTpl', {
tasks: taskAry
});
// 将拼接好的字符串显示在ul标签中
taskBox.html(html);
}
//
success: function(response) {
// console.log(response)
// 将任务添加到任务列表中
taskAry.push(response);
render();
// 清空文本框中的内容
taskInp.val('');
}
完成代码优化,数据的添加功能完成
<button class="destroy" data-id="{{$value._id}}"></button>
// 当用户点击删除按钮时触发ul标签身上的点击事件
taskBox.on('click', '.destroy', function() {
// 要删除的任务的id
var id = $(this).attr('data-id');
// 向服务器端发送请求删除 任务
$.ajax({
url: '/todo/deleteTask',
type: 'get',
data: {
_id: id
},
success: function(response) {
console.log(response);
刷新后
改为不刷新,直接将删除任务的索引好获得,从数组中删除,再重新render到页面上
success: function(response) {
//console.log(response);
// 从任务数组中找到已经删除掉的任务的索引
var index = taskAry.findIndex(item => item._id == id);
// 将任务从数组中删除
taskAry.splice(index, 1);
// 重新将任务数组中的元素显示在页面中
render();
// 计算未完成任务数量
// calcCount()
删除页面功能完成
<li class="{{$value.completed ? 'completed' : ''}}">
<input class="toggle" type="checkbox" {{$value.completed ? 'checked' : ''}}>
//当用户改变任务名称前面的复选框状态时触发
taskBox.on('change', '.toggle', function() {
// 代表复选框是否选中 true 选中 false 未选中的
const status = $(this).is(':checked');
// 当前点击任务的id
const id = $(this).siblings('button').attr('data-id');
// 向服务器端发送请求 更改任务状态
$.ajax({
type: 'post',
url: '/todo/modifyTask',
data: JSON.stringify({
_id: id,
completed: status
}),
contentType: 'application/json',
success: function(response) {
// 将任务状态同步到任务数组中
var task = taskAry.find(item => item._id == id);
// 更改任务状态
task.completed = response.completed;
// 将数组中任务的最新状态更新到页面中
render();
// 计算未完成任务数量
//calcCount ()
}
})
});
完成!
// 当双击事件名称的时候触发
taskBox.on('dblclick', 'label', function() {
// 让任务处于编辑状态
$(this).parent().parent().addClass('editing');
// 将任务名称显示在文本框中
$(this).parent().siblings('input').val($(this).text())
// 让文本框获取焦点
$(this).parent().siblings('input').focus();
})
// 当文本框离开焦点的时候
taskBox.on('blur', '.edit', function() {
// 最新的任务名称
var newTaskName = $(this).val();
// 编辑任务的id
var id = $(this).siblings().find('button').attr('data-id');
// 向服务器端发送请求 修改任务名称
$.ajax({
url: '/todo/modifyTask',
type: 'post',
data: JSON.stringify({
_id: id,
title: newTaskName
}),
contentType: 'application/json',
success: function(response) {
// 将当期任务的最新状态同步到任务数组中
var task = taskAry.find(item => item._id == id);
// 修改任务名称
task.title = response.title;
// 将任务数组中的任务同步到页面中
render();
// // 计算未完成任务数量
// calcCount ()
}
})
});
完成修改
<span class="todo-count"><strong id="count">0</strong> item left</span>
// 用于存储未完成任务数量的strong标签
var strong = $('#count');
// 用于计算未完成任务的数量
function calcCount () {
// 存储结果的变量
var count = 0;
// 将未完成的任务过滤到一个新的数组中
var newAry = taskAry.filter(item => item.completed == false);
// 将新数组的长度赋值给count
count = newAry.length;
// 将未完成的任务数量显示在页面中
strong.text(count)
}
// 计算未完成任务数量
calcCount ()
则未完成任务数量完成
还有几个功能待添加
使用nprogress一个显示进度条
<link rel="stylesheet" href="/js/nprogress/nprogress.css">
<script src="/js/nprogress/nprogress.js"></script>
// 当页面中有ajax请求发送时触发
$(document).on('ajaxStart', function () {
NProgress.start()
})
// 当页面中有ajax请求完成时触发
$(document).on('ajaxComplete', function () {
NProgress.done()
})
完成
07.restful风格的api
// 获取用户列表信息
app.get('/users', (req, res) => {
res.send('当前是获取用户列表信息的路由');
});
// 获取某一个用户具体信息的路由
app.get('/users/:id', (req, res) => {
// 获取客户端传递过来的用户id
const id = req.params.id;
res.send(`当前我们是在获取id为${id}用户信息`);
});
// 删除某一个用户
app.delete('/users/:id', (req, res) => {
// 获取客户端传递过来的用户id
const id = req.params.id;
res.send(`当前我们是在删除id为${id}用户信息`);
});
// 修改某一个用户的信息
app.put('/users/:id', (req, res) => {
// 获取客户端传递过来的用户id
const id = req.params.id;
res.send(`当前我们是在修改id为${id}用户信息`);
});
// 获取用户列表信息
$.ajax({
type: 'get',
url: '/users',
success: function (response) {
console.log(response)
}
})
// 获取id为1的用户信息
$.ajax({
type: 'get',
url: '/users/1',
success: function (response) {
console.log(response)
}
})
// 获取id为1的用户信息
$.ajax({
type: 'delete',
url: '/users/10',
success: function (response) {
console.log(response)
}
})
// 获取id为1的用户信息
$.ajax({
type: 'put',
url: '/users/10',
success: function (response) {
console.log(response)
}
})
完成
关于XML数据的返回,其中参数的获取
app.get('/xml', (req, res) => {
res.header('content-type', 'text/xml');
res.send('<message><title>消息标题</title><content>消息内容</content></message>')
});
<button id="btn">发送请求</button>
<div id="container"></div>
<script type="text/javascript">
var btn = document.getElementById('btn');
var container = document.getElementById('container');
btn.onclick = function () {
var xhr = new XMLHttpRequest();
xhr.open('get', '/xml');
xhr.send();
xhr.onload = function () {
console.log(xhr.responseXML);
xhr.onload = function() {
var xmlDocument = xhr.responseXML;
var title = xmlDocument.getElementsByTagName('title')[0].innerHTML;
container.innerHTML = title;
完成