写在前面,大家好!我是【跨考菌】,一枚跨界的程序猿,专注于后台技术的输出,目标成为
全栈攻城狮
!这博客是对我跨界过程的总结和思考。如果你也对Java
、后端技术
感兴趣,抑或是正在纠结于跨界,都可以关注我的动态,让我们一起学习,一起进步~
我的博客地址为:【跨考菌】的博客
目录
上篇【Ajax编程基础】02 Ajax如何解决跨域问题(小白也能看懂) 介绍了Ajax解决跨域请求的三种途径,本文开始介绍jQuery中发送ajax请求的常用方法。
内容大纲,持续更新:
【Ajax编程基础】01 Ajax基础&异步概述
【Ajax编程基础】02 Ajax如何解决跨域问题(小白也能看懂)
【Ajax编程基础】03 jQuery发送ajax方法(小白也能看懂)
【Ajax编程基础】04 RESTful API实践(小白也能看懂)
源码笔记:
链接:https://pan.baidu.com/s/17DsNEUJupQ6yzuI1f2rJFg
提取码:sxa7
1 $.ajax()
1.1 $.ajax()方法概述
1)作用:发送Ajax请求。
$.ajax({
type: 'get',
url: 'http://www.example.com',
data: { name: 'zhangsan', age: '20' },
contentType: 'application/x-www-form-urlencoded',
beforeSend: function () {
return false
},
success: function (response) {},
error: function (xhr) {}
});
案例1:
<!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: 'get',
// 请求地址
url: '/base',
// 请求成功以后函数被调用
success: function (response) {
// response为服务器端返回的数据
// 方法内部会自动将json字符串转换为json对象
console.log(response);
},
// 请求失败以后函数被调用
error: function (xhr) {
console.log('xhr: ', xhr)
}
})
});
</script>
</body>
</html>
服务端代码:
app.get('/base', (req, res) => {
res.send({
name: 'zhangsan',
age: 30
})
});
案例2:
form-data请求
<!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',
// 向服务器端发送的请求参数
// name=zhangsan&age=100
data: {
name: 'zhangsan',
age: 100
},
// 指定参数的格式类型
contentType: 'application/json',
// 请求成功以后函数被调用
success: function (response) {
// response为服务器端返回的数据
// 方法内部会自动将json字符串转换为json对象
console.log(response);
}
})
});
</script>
</body>
</html>
可以看到参数是以字符串的形式来传递给服务端的。
案例3:
如何以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',
// 向服务器端发送的请求参数
// 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>
1.2 beforeSend方法
如果不想发送请求,return false
即可。
<!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>
1.3 serialize方法
作用:将表单中的数据自动拼接成字符串类型的参数
var params = $('#form').serialize();
// name=zhangsan&age=30
var params2 = obj.serializeArray();
console.log(params2)
// 0: {name: "username", value: "congcong@163.com"}
// 1: {name: "password", value: "congcong"}
案例:
利用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)
var result = serializeObject($(this));
console.log(result)
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;
})
// 将处理的结果返回到函数外部
return result;
}
</script>
</body>
</html>
1.4 发送jsonp请求。
$.ajax({
url: 'http://www.example.com',
// 指定当前发送jsonp请求
dataType: 'jsonp',
// 修改callback参数名称
jsonp: 'cb',
// 指定函数名称
jsonCallback: 'fnName',
success: function (response) {}
})
参数说明:
jsonp:指定服务器端向客户端传递的函数参数,默认是callaback。
jsonCallback:默认调用的是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>
1.5 . g e t ( ) 、 .get()、 .get()、.post()方法概述
作用: . g e t 方 法 用 于 发 送 g e t 请 求 , .get方法用于发送get请求, .get方法用于发送get请求,.post方法用于发送post请求。
$.get('http://www.example.com', {name: 'zhangsan', age: 30}, function (response) {})
$.post('http://www.example.com', {name: 'lisi', age: 22}, function (response) {})
第三个参数实际上是回调函数(success函数)
案例:
<script>
$('#btn').on('click', function () {
$.get('/base', 'name=zhangsan&age=30', function (response) {
console.log(response)
})
$.post('/base', function (response) {
console.log(response)
})
});
</script>
2 Todo案例
2.1 为todo数据库添加账号
- 使用mongo命令进入mongodb数据库
- 使用use admin命令进入到admin数据中
- 使用db.auth(‘root’, ‘root’)命令登录数据库
- 使用use todo命令切换到todo数据库
- 使用db.createUser({user: ‘itcast’, pwd: ‘itcast’, roles: [‘readWrite’]})创建todo数据库账号
- 使用exit命令退出mongodo数据库
2.2 展示任务列表
- 准备一个放置任务列表的数组
- 向服务器端发送请求,获取已存在的任务
- 将已存在的任务存储在任务列表数组中
- 通过模板引擎将任务列表数组中的任务显示在页面中
2.3 添加任务
为文本框绑定键盘抬起事件,在事件处理函数中判断当前用户敲击的是否是回车键
当用户敲击回车键的时候,判断用户在文本框中是否输入了任务名称
向服务器端发送请求,将用户输入的任务名称添加到数据库中,同时将任务添加到任务数组中
通过模板引擎将任务列表数组中的任务显示在页面中
2.4 删除任务
为删除按钮添加点击事件
在事件处理函数中获取到要删任务的id
向服务器端发送请求,根据ID删除任务,同时将任务数组中的相同任务删除
通过模板引擎将任务列表数组中的任务重新显示在页面中
2.5 更改任务状态
为任务复选框添加onchange事件
在事件处理函数中获取复选框是否选中
向服务器端发送请求,将当前复选框的是否选中状态提交到服务器端
将任务状态同时也更新到任务列表数组中
通过模板引擎将任务列表数组中的任务重新显示在页面中并且根据任务是否完成为li元素添加completed类名
2.6 修改任务名称
为任务名称外层的label标签添加双击事件,同时为当前任务外层的li标签添加editing类名,开启编辑状态
将任务名称显示在文本框中并让文本框获取焦点
当文本框离开焦点时,将用户在文本框中输入值提交到服务器端,并且将最新的任务名称更新到任务列表数组中
使用模板引擎重新渲染页面中的任务列表。
2.7 计算未完成任务数量
准备一个用于存储未完成任务数量的变量
将未完成任务从任务数组中过滤出来
将过滤结果数组的长度赋值给任务数量变量
将结果更新到页面中
2.8 显示未完成任务
为active按钮添加点击事件
从任务列表数组中将未完成任务过滤出来
使用模板引擎将过滤结果显示在页面中
2.9 清除已完成任务
为clear completed按钮添加点击事件
向服务器端发送请求将数据库中的已完成任务删除掉
将任务列表中的已完成任务删除调用
使用模板引擎将任务列表中的最后结果显示在页面中
2.10 代码实现:
客户端代码:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Todo List</title>
<link rel="stylesheet" href="assets/css/base.css">
<link rel="stylesheet" href="assets/css/index.css">
<link rel="stylesheet" href="/js/nprogress/nprogress.css">
</head>
<body>
<section class="todoapp">
<header class="header">
<h1>todos</h1>
<input type="text" class="new-todo" placeholder="What needs to be done?" autofocus id="task">
</header>
<!-- This section should be hidden by default and shown when there are todos -->
<section class="main">
<input class="toggle-all" type="checkbox">
<ul class="todo-list" id="todo-list"></ul>
</section>
<!-- This footer should hidden by default and shown when there are todos -->
<footer class="footer">
<!-- This should be `0 items left` by default -->
<span class="todo-count"><strong id="count">0</strong> item left</span>
<!-- Remove this if you don't implement routing -->
<ul class="filters">
<li>
<a class="selected" href="javascript:;">All</a>
</li>
<li>
<a href="javascript:;">Active</a>
</li>
<li>
<a href="javascript:;">Completed</a>
</li>
</ul>
<!-- Hidden if no completed items are left ↓ -->
<button class="clear-completed">Clear completed</button>
</footer>
</section>
<script src="/js/jquery.min.js"></script>
<script src="/js/template-web.js"></script>
<script src="/js/nprogress/nprogress.js"></script>
<!-- 任务列表模板 -->
<script type="text/html" id="taskTpl">
{{each tasks}}
<li class="{{$value.completed ? 'completed' : ''}}">
<div class="view">
<input class="toggle" type="checkbox" {{$value.completed ? 'checked' : ''}}>
<label>{{$value.title}}</label>
<button class="destroy" data-id="{{$value._id}}"></button>
</div>
<input class="edit">
</li>
{{/each}}
</script>
<script type="text/javascript">
// 用于存放任务列表的数组
var taskAry = [];
// 选择任务列表容器
var taskBox = $('#todo-list');
// 添加任务的文本框
var taskInp = $('#task');
// 用于存储未完成任务数量的strong标签
var strong = $('#count');
// 当页面中有ajax请求发送时触发
$(document).on('ajaxStart', function () {
NProgress.start()
})
// 当页面中有ajax请求完成时触发
$(document).on('ajaxComplete', function () {
NProgress.done()
})
// 向服务器端发送请求 获取已经存在的任务
$.ajax({
url: '/todo/task',
type: 'get',
success: function (response) {
// 将已存在的任务存储在taskAry变量中
taskAry = response;
// 拼接字符串 将拼接好的字符串显示在页面中
render();
// 计算未完成任务数量
calcCount ()
}
})
// 获取文本框并且添加键盘抬起事件
taskInp.on('keyup', function (event) {
console.log('event: ', 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) {
// 将任务添加到任务列表中
taskAry.push(response);
// 拼接字符串 将拼接好的字符串显示在页面中
render();
// 清空文本框中的内容
taskInp.val('');
// 计算未完成任务数量
calcCount ()
}
})
}
});
// 拼接字符串 将拼接好的字符串显示在页面中
function render() {
// 字符串拼接
var html = template('taskTpl', {
tasks: taskAry
});
// 将拼接好的字符串显示在ul标签中
taskBox.html(html);
}
// 当用户点击删除按钮时触发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) {
// 从任务数组中找到已经删除掉的任务的索引
var index = taskAry.findIndex(item => item._id == id);
// 将任务从数组中删除
taskAry.splice(index, 1);
// 重新将任务数组中的元素显示在页面中
render();
// 计算未完成任务数量
calcCount ()
}
})
});
// 当用户改变任务名称前面的复选框状态时触发
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 ()
}
})
});
// 用于计算未完成任务的数量
function calcCount () {
// 存储结果的变量
var count = 0;
// 将未完成的任务过滤到一个新的数组中
var newAry = taskAry.filter(item => item.completed == false);
// 将新数组的长度赋值给count
count = newAry.length;
// 将未完成的任务数量显示在页面中
strong.text(count)
}
</script>
</body>
</html>
服务端代码:
// 引入express框架
const express = require('express');
// 工具库
const _ = require('lodash');
// 对象校验
const Joi = require('joi');
// 创建todo案例路由
const todoRouter = express.Router();
// 导入todo集合构造函数
const Task = require('../model/task');
// 获取任务列表
todoRouter.get('/task', async (req, res) => {
const task = await Task.find();
// 响应
res.send(task);
});
// 添加任务
todoRouter.post('/addTask', async (req, res) => {
// 接收客户端传递过来的任务名称
const { title } = req.body;
// 验证规则
const schema = {
title: Joi.string().required().min(2).max(30)
};
// 验证客户端传递过来的请求参数
const { error } = Joi.validate(req.body, schema);
// 验证失败
if (error) {
// 将错误信息响应给客户端
return res.status(400).send({message: error.details[0].message})
}
// 创建任务实例
const task = new Task({title: title, completed: false});
// 执行插入操作
await task.save();
// 响应
setTimeout(() => {
res.send(task);
}, 2000)
});
// 删除任务
todoRouter.get('/deleteTask', async (req, res) => {
// 要删除的任务id
const { _id } = req.query;
// 验证规则
const schema = {
_id: Joi.string().required().regex(/^[0-9a-fA-F]{24}$/)
}
// 验证客户端传递过来的请求参数
const { error } = Joi.validate(req.query, schema);
// 验证失败
if (error) {
// 将错误信息响应给客户端
return res.status(400).send({message: error.details[0].message})
}
// 删除任务
const task = await Task.findOneAndDelete({_id: _id});
// 响应
res.send(task);
});
// 清除已完成任务
todoRouter.get('/clearTask', async (req, res) => {
// 执行清空操作
const result = await Task.deleteMany({completed: true});
// 返回清空数据
res.send(result);
});
// 修改任务
todoRouter.post('/modifyTask', async (req, res) => {
// 执行修改操作
const task = await Task.findOneAndUpdate({_id: req.body._id}, _.pick(req.body, ['title', 'completed']),{new: true})
// 响应
res.send(task);
});
// 查询未完成任务数量
todoRouter.get('/unCompletedTaskCount', async (req, res) => {
// 执行查询操作
const result = await Task.countDocuments({completed: false});
// 响应
res.send({num: result})
});
// 更改任务全部状态
todoRouter.get('/changeAllTasksComplete', async (req, res) => {
// 状态
const { status } = req.query;
// 执行更改状态操作
const result = await Task.updateMany({}, {completed: status});
// 响应
res.send(result);
});
// 将todo案例路由作为模块成员进行导出
module.exports = todoRouter;
3 jQuery中Ajax全局事件
3.1 全局事件
场景:在网速比较慢的时候,希望给出等待响应提示信息,怎么实现呢?
只要页面中有Ajax请求被发送,对应的全局事件就会被触发
.ajaxStart() // 当请求开始发送时触发
.ajaxComplete() // 当请求完成时触发
案例:
// 当页面中有ajax请求发送时触发
$(document).on('ajaxStart', function () {
// 这里可以给出提示信息。
NProgress.start()
})
// 当页面中有ajax请求完成时触发
$(document).on('ajaxComplete', function () {
NProgress.done()
})
其中,NProgress:纳米级进度条,使用逼真的涓流动画来告诉用户正在发生的事情!
<link rel='stylesheet' href='nprogress.css'/>
<script src='nprogress.js'></script>
NProgress.start(); // 进度条开始运动
NProgress.done(); // 进度条结束运动
如果你觉得内容对您有帮助的话,记得给博主一键三连😊哦