一、客户端与服务器
略
二、URL地址
2.1 URL概念
统一资源定位符
2.2 URL组成部分
一般由三部分组成
①客户端与服务器之间的通信协议
②存有该资源的服务器名称
③资源在服务器上具体的存放位置
三、分析网页打开过程
客户端发送请求服务器 --> 服务器处理请求 --> 服务器响应客户端
四、服务器对外提供了哪些资源
4.1 数据
- 网页中的数据也是资源
- 数据是网页的灵魂
- 数据也是请求–>处理–>响应
网页中请求服务器上的数据资源,要用到XMLHttpRequest()对象
let xhrObj = new XMLHttpRequest()
4.2 请求方式
get方式(获取)和post(提交)方式
五、了解Ajax
5.1 Ajax
Ajax的全称是Asynchronous Javascript And XMl(异步、 JavaScript 和 XML)
也就是:在网页中利用XMLHttpRequest 对象和服务器进行数据交互的方式,就是Ajax
5.2 Ajax作用
实现网页与服务器之间的数据交互
5.3 Ajax的典型应用场景
①检测用户名是否被占用
②加载搜索提示列表
③根据页码值动态刷新表格数据
④数据的增删改查
六、jQuery中的Ajax
浏览器中的XMLHttpRequest用法比较复杂,而jQuery对XMlHttpRequest进行封装,提供了一系列Ajax相关函数,极大地降低了Ajax的使用难度
6.1 常用方法
- $.get() 获取
- $.post() 提交
- $.ajax() 既可以获取,也可以提交
6.2 $.get()语法
$.get(url, [data], [callback])
参数名 | 参数类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 要请求的资源地址 |
data | object | 否 | 请求资源期间要携带的参数 |
callback | fuction | 否 | 请求成功时的回调函数 |
6.3 $.post()语法
$.post(url, [data], [callback])
参数名 | 参数类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 要提交的数据地址 |
data | object | 否 | 要提交的数据 |
callback | fuction | 否 | 数据提交成功时的回调函数 |
6.4 $.ajax()语法
$.ajax({
type: '', // 请求方式,例如 GEST 或 POST
url: '', // 请求的 URL 地址
datd: {}, // 这次请求要携带的数据
success: function(res) {} // 请求成功之后的回调函数
})
七、接口
使用Ajax请求数据时,被请求的URL地址,就叫做数据接口(简称接口)。同时,每个接口必须有请求方式。
过程:请求 --> 处理 --> 响应
7.1 接口测试工具
不写任何代码情况下,对接口进行调用和测试
PostMan:https://www.postman.com/downloads/
7.2 接口文档
接口的说明文档,它是我们调用接口的依据。
好的接口文档包含了对接口URL,参数以及输出内容的说明,我们参照接口文档就能方便的知道接口的作用,以及接口如何进行调用。
组成部分:
①接口名称:用来标识各个接口的简单说明,如登录接口、获取信息列表接口等。
②接口URL:接口的调用地址。
③调用方式:接口的调用方式,如GET或POST。
④参数格式:接口需要传递的参数,每个参数必须包含参数名称、参数类型、是否必选、参数说明这4项说明。
⑤响应格式:接口返回值的详细描述,一般包括数据名称、数据类型和说明3项内容。
⑥返回示例(可选):通过对象的形式,列举服务器返回数据的结构。
八、案例
8.1 图书管理
目标
通过ajax连接后台,进行后台图书数据的增删,然后将图书数据显示到页面上。
用到的css库 bootstrap.css
用到的javascript库jquery.js
用到的vscode 插件 Bootstrap 3 Snippets
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图书管理</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<script src="js/jquery.min.js"></script>
</head>
<body style="padding: 15px;">
<!-- 添加图书馆的Panel面板 -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加新图书</h3>
</div>
<div class="panel-body form-inline">
<div class="input-group">
<div class="input-group-addon">书名</div>
<input type="text" class="form-control" id="iptBookname" placeholder="请输入书名">
</div>
<div class="input-group">
<div class="input-group-addon">作者</div>
<input type="text" class="form-control" id="iptAuthor" placeholder="请输入作者">
</div>
<div class="input-group">
<div class="input-group-addon">出版社</div>
<input type="text" class="form-control" id="iptPublisher" placeholder="请输入出版社">
</div>
<button id="btnAdd" class="btn btn-primary">添加</button>
</div>
</div>
<!-- 图书表格 -->
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>ID</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th>操作</th>
</tr>
</thead>
<tbody id="tb">
<!-- <tr>
<td></td>
</tr> -->
</tbody>
</table>
<script>
$(function() {
function getBooklist() {
// get请求数据
$.get('http://www.liulongbin.top:3006/api/getbooks', function(res) {
// console.log(res);
if (res.status !== 200) return alert('获取数据失败!');
let rows = [];
// 遍历获得的数据
$.each(res.data, function(i, item) {
rows.push('<tr><td>' + item.id + '</td><td> ' + item.bookname + ' </td><td> ' + item.author + ' </td><td> ' + item.publisher + ' </td><td><a href="javascript:;" class="del" data-id= ' + item.id + ' ></a></td></tr>')
});
// 清空tbody,再追加数组rows join('')表示用空字符串拼接
$('#tb').empty().append(rows.join(''));
});
};
getBooklist();
// 事件代理删除操作
$('#tb').on('click', '.del', function() {
let id = $(this).data('id');
$.get('http://www.liulongbin.top:3006/api/delbooks', {id: id}, function(res) {
if (res.status !== 200) return alert('删除图书失败!');
getBooklist();
});
});
// 添加图书
$('#btnAdd').on('click', function() {
// .trim() 去除字符串首尾空格
let bookname = $('#iptBookname').val().trim();
let author = $('#iptAuthor').val().trim();
let publisher = $('#iptPublisher').val().trim();
if (bookname.length <= 0 || author.length <= 0 || publisher.length <= 0) {
return alert('请填写完整的图书信息!');
} else {
// alert('添加成功!');
$.post('http://www.liulongbin.top:3006/api/addbook',
{bookname: bookname, author: author, publisher: publisher},
function(res) {
if (res.atatus != 201) return alert('添加图书失败!');
getBooklist();
$('#iptBookname').val('');
$('#iptAuthor').val('');
$('#iptPublisher').val('');
})
}
});
});
</script>
</body>
</html>
8.2 聊天机器人
chat.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/main.css" />
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery-ui.min.js"></script>
<script type="text/javascript" src="js/jquery.mousewheel.min.js"></script>
<title>聊天机器人</title>
</head>
<body>
<div class="wrap">
<!-- 头部 Header 区域 -->
<div class="header">
<h3>小思同学</h3>
<img src="img/person01.png" alt="icon" />
</div>
<!-- 中间 聊天内容区域 -->
<div class="main">
<ul class="talk_list" style="top: 0px;" id="talk_list">
<li class="left_word">
<img src="img/person01.png" /> <span>嗨,你最近有想我吗? </span>
</li>
<li class="right_word">
<img src="img/person02.png"> <span>哈喽,我很想你! </span>
</li>
<li class="left_word">
<img src="img/person01.png" /> <span>讨厌啦(✿◡‿◡) </span>
</li>
</ul>
<div class="drag_bar" style="display: none;">
<div class="drager ui-draggable ui-draggable-handle" style="display: none; height: 412.628px;"></div>
</div>
</div>
<!-- 底部 消息编辑区域 -->
<div class="footer">
<img src="img/person02.png" alt="icon" />
<input type="text" placeholder="说些什么吧..." class="input_txt" id="ipt" />
<input type="button" value="发 送" class="input_sub" id="btnSend" />
</div>
</div>
<!-- 注意 只要为audio指定了新的src属性 而且绑定了 autoplay style="display: none;" 语音会自动播放 并且隐藏起来 -->
<audio src="" id="voics" autoplay style="display: none;"></audio>
<!-- 只有插入axios.js文件才可以使用ajax的库 -->
<script src="js/axios.js"></script>
<!-- 为了重置滚动条位置 -->
<script type="text/javascript" src="js/scroll.js"></script>
<script src="js/chat.js"></script>
</body>
</html>
main.css
body {
font-family: 'Microsoft YaHei';
}
.wrap {
position: fixed;
width: 450px;
left: 50%;
margin-left: -225px;
top: 20px;
bottom: 20px;
border: 1px solid #ebebeb;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.header {
height: 55px;
background: linear-gradient(90deg, rgba(246, 60, 47, 0.6), rgba(128, 58, 242, 0.6));
overflow: hidden;
}
.header h3 {
color: #faf3fc;
line-height: 55px;
font-weight: normal;
float: left;
letter-spacing: 2px;
margin-left: 25px;
font-size: 18px;
text-shadow: 0px 0px 5px #944846;
}
.header img {
float: right;
margin: 7px 25px 0 0;
border-radius: 20px;
box-shadow: 0 0 5px #f7f2fe;
}
.main {
position: absolute;
left: 0;
right: 0;
top: 55px;
bottom: 55px;
background-color: #f4f3f3;
box-sizing: border-box;
padding: 10px 0;
overflow:hidden;
}
.talk_list{
position: absolute;
width:100%;
left:0px;
top:0px;
}
.talk_list li {
overflow: hidden;
margin: 20px 0px 30px;
}
.talk_list .left_word img {
float: left;
margin-left: 20px;
}
.talk_list .left_word span {
float: left;
background-color: #fe9697;
padding: 10px 15px;
max-width: 290px;
border-radius: 12px;
font-size: 16px;
color: #fff;
margin-left: 13px;
position: relative;
line-height: 24px;
}
.talk_list .left_word span:before {
content: '';
position: absolute;
left: -8px;
top: 3px;
width: 13px;
height: 12px;
background: url('../img/corner01.png') no-repeat;
}
.talk_list .right_word img {
float: right;
margin-right: 20px;
}
.talk_list .right_word span {
float: right;
background-color: #fff;
padding: 10px 15px;
max-width: 290px;
border-radius: 12px;
font-size: 16px;
color: #000;
margin-right: 13px;
position: relative;
line-height: 24px;
}
.talk_list .right_word span:before {
content: '';
position: absolute;
right: -8px;
top: 3px;
width: 13px;
height: 12px;
background: url('../img/corner02.png') no-repeat;
}
.drag_bar{
position:absolute;
right:0px;
top:0px;
background-color: #fff;
height:100%;
width:6px;
box-sizing:border-box;
border-bottom:1px solid #f4f3f3;
}
.drager{
position:absolute;
left:0px;
top:0px;
background-color: #cdcdcd;
height:100px;
width:6px;
border-radius:3px;
cursor: pointer;
}
.footer{
width:100%;
height: 55px;
left:0px;
bottom:0px;
background-color:#fff;
position: absolute;
}
.footer img{
float: left;
margin:8px 0 0 20px;
}
.input_txt{
float: left;
width:270px;
height:37px;
border:0px;
background-color: #f4f3f3;
margin:9px 0 0 20px;
border-radius:8px;
padding:0px;
outline:none;
text-indent:15px;
}
.input_sub{
float: left;
width:70px;
height:37px;
border:0px;
background-color: #fe9697;
margin:9px 0 0 15px;
border-radius:8px;
padding:0px;
outline:none;
color:#fff;
cursor: pointer;
}
reset.css
body,ul,h1,h2,h3,h4,h5,h6{
margin: 0;
padding: 0;
}
h1,h2,h3,h4,h5,h6{
font-size:100%;
font-weight:normal;
}
a{
text-decoration:none;
}
ul{
list-style:none;
}
img{
border:0px;
}
/* 清除浮动,解决margin-top塌陷 */
.clearfix:before,.clearfix:after{
content:'';
display:table;
}
.clearfix:after{
clear:both;
}
.clearfix{
zoom:1;
}
.fl{
float:left;
}
.fr{
float:right;
}
chat.js
$(function () {
// 调用scroll,重置滚动条位置
resetui();
/*
1.点击发送按钮或者按下回车键
1.1 获取输入框文本
1.2 非空判断
1.3 生成自己的聊天框
1.4 发送ajax请求机器人聊天内容
1.5 生成机器人的聊天框
2.数据驱动思路 : 把dom增删改查 改成 数组增删改查
(1)声明一个全局空数组,用于存储聊天内容 let list = []
(2)将聊天内容添加到数组 list.push({text:聊天内容, isMe:true})
(3)渲染数组
3.文字转语音思路
(1)发送ajax请求: 把文字发给服务器
(2)服务器响应返回音频url
(3)给页面添加一个<audio>标签, 把服务器返回的音频url设置给 audio标签的src属性
*/
$('#btnSend').on('click', function () {
let text = $('#ipt').val().trim();
if (text.length <= 0) {
return $('#ipt').val('');
}
// 如果输入了聊天内容,就追加到页面上去
$('#talk_list').append('<li class="right_word"><img src="img/person02.png"> <span>' + $('#ipt').val() + ' </span></li>');
$('#ipt').val('');
// 调用scroll,重置滚动条位置
resetui();
// 发送请求,获取回应
getMag($('#ipt').val(''));
});
// 获取机器人的回应,并渲染到页面中
function getMag(text) {
$.ajax({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/robot',
data: {
spoken: text
},
success: function (res) {
// console.log(res);
if (res.message == 'success') {
// 请求成功 接受聊天消息
let msg = res.data.info.text;
$('#talk_list').append('<li class="left_word"><img src="img/person01.png"> <span>' + msg + ' </span></li>');
// 调用scroll,重置滚动条位置
resetui();
// 调用把文字转成语音的函数
playVoice(msg);
}
}
});
};
// 自动播放语音
function playVoice(text) {
$.ajax({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/synthesize',
data: {
text: text
},
success: function (res) {
if (res.status === 200) {
// 设置 audio 标签的src属性
$('#voice').attr('src', res.voiceUrl);
}
}
});
};
// 优化 - 在输入框里按回车,也能够发送(让按回车的效果和点击发送按钮的效果一样)
$('#ipt').keyup(function (e) {
// 键盘弹起之后,触发的函数
// 获取键盘的keyCode值
// let keyCode = e.keyCode; // jQuery封装的属性,可以获取到键盘的keyCode
let keyCode = e.which; // jQuery封装的属性,也可以获取到键盘的keyCode
// console.log(keyCode);
// 判断,是否按的是回车键
if (keyCode === 13) {
// 说明按了回车键
// 解决方案一:renderMyWord($(this).val().trim());
// 解决方案二:触发 发送按钮的单击事件
// $('#btnSend').click(); //
$('#btnSend').trigger('click');
}
});
})
九、form与模版引擎
9.1 form表单的基本使用
- GET方式提交表单,我们输入的值(请求参数)会拼接到url后面。
- POST方式提交表单,请求参数,不会拼接到url上。
解决表单同步提交的缺点
缺点:
①页面会跳转
②页面之前的状态和数据会丢失
解决方案:表单只负责采集数据,Ajax负责将数据提交到服务器
9.2 通过Ajax提交表单数据
快速获取表单中的数据
$(selector).serialize() // 一次性获取表单中的所有数据
注意:
①结果是键值对的形式
②必须为每一个表单元素添加name属性
9.3 案例-评论列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>评论列表</title>
<link rel="stylesheet" href="css/bootstrap.min.css" />
<script src="js/jquery.min.js"></script>
</head>
<body style="padding: 15px;">
<!-- 评论面板 -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">发表评论</h3>
</div>
<form class="panel-body" id="formAddCmt">
<div>评论人:</div>
<input type="text" class="form-control" name="username" />
<div>评论内容:</div>
<textarea class="form-control" name="content"></textarea>
<button type="submit" class="btn btn-primary">发表评论</button>
</form>
</div>
<!-- 评论列表 -->
<ul class="list-group">
<li class="list-group-item">
<span class="badge" style="background-color: #F0AD4E;">评论时间:</span>
<span class="badge" style="background-color: #5BC0DE;">评论人:</span>
Item
</li>
</ul>
<script>
$(function () {
function getCommentList() {
$.ajax({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/cmtlist',
success: function (res) {
if (res.status !== 200) return alert('获取评论失败!')
let rows = [];
$.each(res.data, function (i, item) {
let str = '<li class="list-group-item"><span class="badge" style="background-color: #F0AD4E;">评论时间:' + item.time + '</span><span class="badge" style="background-color: #5BC0DE;">评论人:' + item.username + '</span>' + item.content + '</li>';
rows.push(str)
});
$('#cmt-list').append(rows.join(''));
}
});
};
getCommentList();
$('#formAddCmt').on('submit', function (e) {
e.preventDefault();
let data = $(this).serialize();
// console.log(data);
$.post('http://www.liulongbin.top:3006/api/addcmt', data, function(res) {
if (res.status !== 201) {
return alert('发表评论失败!')
}
getCommentList();
// 原生的重置表单
$('#formAddCmt')[0].reset();
})
});
})
</script>
</body>
</html>
9.4 模版引擎的基本概念
解决字符串拼接的问题、结构清晰、易于维护和阅读
模版引擎,顾名思义,他可以根据程序员指定的模板结构和数据,自动生成一个完整的HTML页面。
9.5 art-template模版引擎
中文官网:http://aui.github.io/art-template/zh-cn/index.html
9.5.1 art-template的标准语法
**{{}}**是art-template的标准语法(变量填充、循环数组)
- 在{{}}语法中,可以进行变量的输出、对象属性的输出、三元表达式输出、加减乘除等表达式输出
①原文输出
{{@ value}},
输出包含HTML标签结构的内容,保证正常渲染
②条件输出
在{{}}中使用 if…else if…/if 的方式,进行按需输出
{{if value}} 按需输出的内容 {{/if}}
{{if v1}} 按需输出的内容 {{else if v2}} {{/if}}
③循环输出
在{{}}内部通过each语法循环数组,当前循环的索引使用 $index 进行访问,当前的循环项使用 $value 进行访问
{{each arr}}
{{$index}} {{$value}}
{{/each}}
④过滤器
{{value | filterName}}
管道操作符,他的上一个输出座位下一个输入
template.defaults.imports.filterName = function(value){/*return 处理的结果*/}
模版引擎
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模版引擎</title>
<script src="js/jquery.min.js"></script>
<!-- 多一个template函数(需要模版id和数据对象) -->
<script src="js/template-web.js"></script>
</head>
<body>
<div class="container"></div>
<!-- 定义模版 -->
<script type="text/html" id="tpl-user">
<h3>{{name}}:{{age}}岁</h3>
{{@ test}}
<div>
{{if flag === 0}}
flag的值是0
{{else if flag !== 0}}
flag的值不是0
{{/if}}
</div>
<ul>
{{each hobby}}
<li>索引是: {{$index}},循环项是: {{$value}}</li>
{{/each}}
</ul>
<div>注册时间:{{regTime | dateFormat}}</div>
</script>
<script>
// 数据
let data = {
name: 'ssy',
age: 23,
test: '<h2>哈哈哈哈!</h2>',
flag: 1,
hobby: ['吃饭', '睡觉', '写代码'],
regTime: new Date()
};
// 过滤器处理函数
template.defaults.imports.dateFormat = function (date) {
// console.log(date);
let y = date.getFullYear();
let m = date.getMonth();
let d = date.getDate();
return y + '-' + m + '-' + d; // 注意,过滤器最后一定要return一个值
};
// 调用template函数
let htmlStr = template('tpl-user', data);
console.log(htmlStr);
// 渲染HTML结构
$('.container').html(htmlStr);
</script>
</body>
</html>
9.5.2 案例-新闻列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新闻列表</title>
<style>
.news-item {
display: flex;
border: 1px solid #eee;
width: 700px;
padding: 10px;
margin-bottom: 5px;
}
.thumb {
display: block;
width: 230px;
height: 140px;
background-color: #ccc;
margin-right: 10px;
}
.right-box {
display: flex;
flex-direction: column;
justify-content: space-between;
font-size: 12px;
flex: 1;
}
.title {
font-size: 20px;
font-weight: normal;
}
.tags span {
display: block;
float: left;
background-color: #F0F0F0;
line-height: 20px;
padding: 0 10px;
border-radius: 10px;
margin-right: 8px;
}
.footer {
display: flex;
justify-content: space-between;
}
</style>
<script src="js/jquery.min.js"></script>
<script src="js/template-web.js"></script>
</head>
<body>
<div id="news-list">
<div class="news-item">
<img class="thumb" src="" alt="" />
<div class="right-box">
<h1 class="title">5G商用在即,三大运营商营收持续下降</h1>
<div class="tags">
<span>三大运营商</span>
<span>中国移动</span>
<span>5G商用</span>
</div>
<div class="footer">
<div>
<span>胡润百富</span>
<span>2023-05-22 20:28:38</span>
</div>
<span>评论数:66</span>
</div>
</div>
</div>
</div>
<!-- 定义模板 -->
<script type="text/html" id="tpl-news">
<!-- {{data.length}} -->
{{each data}}
<div class="news-item">
<img class="thumb" src="{{'http://www.liulongbin.top:3006' + $value.img}}" alt="" />
<div class="right-box">
<h1 class="title">{{$value.title}}</h1>
<div class="tags">
<!-- 循环遍历划分好的字符串数组 -->
{{each $value.tags}}
<span>{{$value}}</span>
{{/each}}
<!-- <span>中国移动</span>
<span>5G商用</span> -->
</div>
<div class="footer">
<div>
<span>{{$value.source}}</span>
<span>{{$value.time | dateFormat}}</span>
</div>
<span>评论数:{{$value.cmtcount}}</span>
</div>
</div>
</div>
{{/each}}
</script>
<script>
$(function () {
function padZero(n) {
n < 10 ? '0' + n : n;
}
// 定义时间过滤器
template.defaults.imports.dateFormat = function (dtStr) {
let dt = new Date(dtStr);
let y = date.getFullYear();
let m = padZero(date.getMonth() + 1);
let d = padZero(date.getDate());
let hh = padZero(date.getHours());
let mm = padZero(date.getMinutes());
let ss = padZero(date.getSeconds());
return y + '-' + m + '-' + d + '' + hh + ':' + mm + ':' + ss;
}
// 获取新闻列表数据
function getNewsList() {
$.get('http://www.liulongbin.top:3006/api/news', function (res) {
if (res.status != 200) {
return alert('获取新闻列表数据失败!');
}
// 把每一项的 tags 属性,从字符串转化为字符串数组
for (let i = 0; i < res.data.length; i++) {
res.data[i].tags = res.data[i].tags.split(',');
}
// console.log(res.data);
let htmlStr = template('tpl-news', res);
$('#new-list').html(htmlStr);
});
};
getNewsList();
})
</script>
</body>
</html>
9.6 模版引擎的实现原理
9.6.1 正则回顾
- 区分正则方法和字符串方法
- 正则方法
- test()
- exec()
- 字符串方法
- match()
- replace()
- split()
- search()
- 正则方法
正则方法由正则表达式调用;字符串方法由字符串调用;
- exec方法
- 功能:使用正则表达式匹配字符串,返回值中包含匹配的结果
- 特点:
- 一次只能匹配一个结果
- 再次调用将匹配下一个结果
- 没有更多匹配则返回null
- 如果正则表达式中有捕获(小括号),则返回值中包括捕获的结果
- replace方法
- 功能:字符串替换
- 特点:
- 可以使用正则表达式进行匹配搜索
- 可以使用函数完成高级的替换
- 正则分组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>正则分组</title>
</head>
<body>
<script>
// let str = '<div>我是{{name}},今年{{ age }}岁了</div>';
// let pattern = /{{\s*([a-zA-Z]+)\s*}}/;
// // 第一次匹配
// let result = pattern.exec(str);
// console.log(result);
// str = str.replace(result[0], result[1]);
// console.log(str); // 输出 <div>我是name,今年{{ age }}岁了</div>
// // 第二次匹配
// result = pattern.exec(str);
// console.log(result);
// str = str.replace(result[0], result[1]);
// console.log(str); // 输出 <div>我是name,今年age岁了</div>
// // 第三次匹配
// result = pattern.exec(str);
// console.log(result); // 输出 null
// document.write(str);
// 循环简化多次
let data = {name: '张三', age: 20};
console.log(data.name);
let str = '<div>我是{{name}},今年{{ age }}岁了</div>';
let pattern = /{{\s*([a-zA-Z]+)\s*}}/;
let patternResult = null;
while(patternResult = pattern.exec(str)) { // 最后patternResult结果为null跳出
str = str.replace(patternResult[0], data[patternResult[1]]); // 不支持 data.patternResult[1]
}
console.log(str);
document.write(str);
</script>
</body>
</html>
9.6.2 实现简易的模板引擎
步骤:
① 定义模版引擎
② 预调用模板引擎
③ 封装template函数
④导入并使用自定义的模板引擎
自定义简易的模版引擎函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>简易的模版引擎</title>
<script src="js/jquery.min.js"></script>
</head>
<body>
<div id="user-box"></div>
<script type="text/html" id="tpl-user">
<div>姓名:{{name}}</div>
<div>年龄:{{ age }}</div>
<div>性别:{{ gender}}</div>
<div>住址:{{address }}</div>
</script>
<script>
// 自定义简易的template函数
function template(id, data) {
let str = document.getElementById(id).innerHTML
let pattern = /{{\s*([a-zA-Z]+)\s*}}/
let patternResult = null
while (patternResult = pattern.exec(str)) { // 最后patternResult结果为null跳出
str = str.replace(patternResult[0], data[patternResult[1]])
}
return str
}
// 定义数据
let data = { name: 'Tony', age: 28, gender: '男', address: '河南省郑州市' }
// 调用模版引擎
let htmlStr = template('tpl-user', data)
// 渲染
$('#user-box').html(htmlStr)
</script>
</body>
</html>
十、Ajax加强
10.1 XMLHttpRequest的基本使用
10.1.1 使用xhr发起GET请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XMLHttpRequest</title>
</head>
<body>
<script>
// 1.创建 XHR 对象
let xhr = new XMLHttpRequest();
//2.调用 open 函数,指定 请求方式 与 URl 地址
xhr.open('GET', 'https://autumnfish.cn/api/joke/list?num=5')
// 3.调用 send 函数,发起 Ajax 请求
xhr.send()
// 4.监听 onreadystatuschange 事件
xhr.onreadystatechange = function () {
// 4.1 监听 xhr 对象的请求状态 readyState ; 与服务器响应的 status状态
if (xhr.readyState === 4 && xhr.status === 200) {
// 4.2 打印服务器响应回来的数据
console.log(xhr.responseText);
}
}
</script>
</body>
</html>
10.1.2 xhr对象的readyStatus属
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | XMLHttpRequest对象已被创建,但尚未被调用 |
1 | OPEND | open()方法已经被调用 |
2 | HEADERS_RECEIVED | send()方法已经被调用,响应头也已经被接受 |
3 | LOADNG | 数据接受中,此时response属性中已经包含部分数据 |
4 | DONE | Ajax请求完成,这意味着数据传输已经被彻底完成或失败 |
10.1.3 URL编码
浏览器会自动处理,我们一般不需太留意
// 编码
encodeURI('红&黑');
// "%E7%BA%A2&%E9%BB%91"
encodeURIComponent('红&黑');
// "%E7%BA%A2%26%E9%BB%91"
// 解码
decodeURI('%E7%BA%A2&%E9%BB%91');
// "红&黑"
decodeURIComponent("%E7%BA%A2%26%E9%BB%91");
// "红&黑"
在实际开发中,需要对中文及需要编码的特殊符号进行URL编码与解码:
使用的编码函数:
- encodeURI() — 能够对中文进行编码
- encodeURIComponent() — 能够对中文和特殊符号进行编码(&=)
使用的解码函数:
- decodeUPI() — 能够对中文进行解码
- decodeURIComponent() — 能够对中文和特殊符号进行解码(&=)
10.1.4 xhr发起POST方式的请求
和GET方式的两个区别:
- 必须在open和send之间,加一个请求头
- 查询字符串的位置变化为send的参数
// 1. 创建 xhr 对象
let xhr = new XMLHttpRequest();
// 2. 调用open,设置请求方式和url
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');
// 3. POST方式,要设置请求头 --- 和GET方式不一样的一处
// 下面一行代码的意思,告诉服务器,前端提交的数据是什么类型的。表示是查询字符串类型
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 4. 调用send,发送请求
// xhr.send('key=value&key=valuye.......');
xhr.send('bookname=唐诗三百首&author=老汤&publisher=黑马出版社');
// 5. 注册 onreadystatechange 事件
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
let res = JSON.parse(this.responseText);
console.log(res);
}
}
10.2 数据交换格式
服务器端与客户端之间进行数据传输与交换的格式,常用XML(标记语言,常用来传输数据和存储数据)和JSON(本质是字符串)
10.2.1 JSON
写法:
-
一个json文件(数据),最大的括号或者数组框只能有一个
-
字符串,属性名和字符串必须使用双引号,不能使用单引号
-
不能写注释
-
json中不能有 undefined
**两种结构:**对象结构(键值对形式)、数组结构
JSON的数据类型:number、string、null、bool、array、object
序列化:把数据对象转化为字符串的过程叫做序列化,例如:调用JSON.stringify()函数操作,叫做JSON序列化
反序列化:把字符串转化为数据对象的过程叫做序列化,例如:调用JSON.parse()函数操作,叫做JSON反序列化
10.3 封装自己的Ajax函数
<script>
// 对象转化为拼接字符串函数
function resolveData(data) {
let arr = []
for (let k in data) {
let str = k + '=' + data[k]
arr.push(str)
}
return arr.join('&')
}
// let ss = resolveData({num: 5})
// console.log(ss);
// 模拟 $.ajax() ,自己封装一个实现ajax请求的函数
/*
option 是一个对象
option.method 表示请求类型
option.url 表示请求的url
option.data 表示请求参数
option.success() 表示一个处理服务器返回结果的函数
*/
function ajax(options) {
let xhr = new XMLHttpRequest();
// 把传过来的参数转化为 查询拼接字符串
let qs = resolveData(options.data)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status == 200) {
let result = JSON.parse(xhr.responseText) // 对象
options.success(result)
}
}
// toUpperCase()转化为大写
if (options.method.toUpperCase() === 'GET') {
// GET请求
xhr.open('GET', options.url + '?' + qs)
xhr.send()
} else if (options.method.toUpperCase() === 'POST') {
// POST请求
xhr.open('POST', options.url)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(qs)
}
}
</script>
<script>
ajax({
method: 'geT',
url: 'https://autumnfish.cn/api/joke/list',
data: {
num: 5
},
success: function(res) {
console.log(res);
}
})
ajax({
method: 'post',
url: 'http://www.liulongbin.top:3006/api/addbook',
data: {
bookname: '唐诗三百首',
author: '老汤',
publisher: '黑马出版社'
},
success: function(res) {
console.log(res);
}
})
</script>
10.4 XMLHttpRequest Level2的新特性
旧版XMLHttpRequest缺点:
①只支持文本数据传输,无法用来读取和上传
②传送和接收数据是,没有进度条,只能提示有没有完成
XMLHttpRequest Level2的新功能
① 可以设置HTTP请求权限
② 可以使用FormData对象管理表单数据
③ 可以上传
④ 可以获得数据传输的进度信息
timeout、FormData、xhr.upload.onprogress、xhr.upload.onload
<body>
<form id="form1">
<!-- autocomplete="off" 阻止自动填充 -->
<input type="text" name="uname" autocomplete="off">
<input type="password" name="upwd">
<button type="submit">提交</button>
</form>
<br>
<input type="file" id="file1" />
<br>
<button id="btnUpload">上传文件</button>
<br>
<!-- 进度条 -->
<div class="progress" style="width: 600px; margin-top: 10px;">
<div class="progress-bar progress-bar-striped active" style="width: 45%" id="percent">
45%
</div>
</div>
<br>
<img src="" alt="" id="img" width="800">
<script>
let xhr = new XMLHttpRequest()
// // 设置超时时间
// xhr.timeout = 30
// // 添加timeout事件
// xhr.ontimeout = function(e) {
// alert('请求超时了!')
// }
// 获取表单元素
let form = document.querySelector('#form1')
form.addEventListener('submit', function (e) {
e.preventDefault()
// 创建FormData对象 并接受form中数据
let fd = new FormData(form)
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
}
})
// // 创建FormData对象
// let fd = new FormData()
// // 为FormData添加表单项
// fd.append('uname', 'ssy')
// fd.append('upwd', '121212')
// xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// // 可以省略xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// xhr.send(fd)
// xhr.onreadystatechange= function() {
// if (xhr.readyState === 4 && xhr.status === 200) {
// console.log(JSON.parse(xhr.responseText));
// }
// }
// 获取上传文件按钮
let btnUpload = document.querySelector('#btnUpload')
btnUpload.addEventListener('click', function () {
let files = document.querySelector('#file1').files
if (files.length <= 0) {
return alert('请选择要上传的文件!')
} else {
// 创建FormData对象
let fd = new FormData()
// 为FormData添加表单项
fd.append('avatar', files[0])
let xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
// 监听文件上传进度
xhr.upload.onprogress = function (e) {
// e.lengthComputable是一个布尔值,表示当前上传的资源是否具有可计算的长度
if (e.lengthComputable) {
// e.loaded 已传输的字节
// e.total 需传输德总字节
// ceil()取整
let percentComplete = Math.ceil((e.loaded / e.total) * 100)
console.log(percentComplete);
document.querySelector('#percent').style.width = percentComplete + '%'
document.querySelector('#percent').innerHTML = percentComplete + '%'
}
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
data = SON.parse(xhr.responseText)
console.log(data);
if (data.status == 200) { // 成功上传
// 将服务器返回的图片地址。设置为img标签的src属性
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else {
console.log(data.message);
}
}
}
xhr.upload.onload = function () {
let percent = document.querySelector('#percent')
percent.classList.remove('progress-bar-striped')
percent.classList.add('progress-bar-success')
}
}
})
</script>
</body>
10.5 jQuery高级用法
10.5.1 jQuery实现文件上传
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery高级用法</title>
<script src="js/jquery.min.js"></script>
</head>
<body>
<input type="file" id="file1">
<button id="btnUpload">上传文件</button>
<script>
$('#btnUpload').on('click', function () {
// 转化为原生的对象
let files = $('#file1')[0].files
if (files.length <= 0) {
return alert('请选择文件后再上传!')
}
let fd = new FormData()
fd.append('avatar', files[0])
$.ajax({
method: 'POST',
url: 'http://www.liulongbin.top:3306/api/upload/avatar',
data: fd,
// 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
processData: false,
// 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
contentType: false,
success: function(res) {
console.log(res);
}
})
})
</script>
</body>
</html>
10.5.2 jQuery实现loading效果
① ajaxStart(callback)
Ajax请求开始时,执行ajaxStart函数。可以在ajaxStart的callback中显示loading效果
注意:$(document).ajaxStart()函数会监听当前文档内所有的Ajax请求。
② ajaxStop(callback)
Ajax请求结束时,执行ajaxStop函数。可以在ajaxStop的callback中隐藏loading效果
③ $.ajaxPrefilter();
在每个ajax请求发送之前,自定义ajax的选项或修改ajax的选项。
$.ajaxPrefilter(function (options) {
// options是当前ajax请求的所有选项
// 得到ajax请求的所有选项之后,可以对他进行修改
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jQuery高级用法</title>
<script src="js/jquery.min.js"></script>
</head>
<body>
<input type="file" id="file1">
<button id="btnUpload">上传文件</button>
<br>
<img src="images/loaing机械.gif" alt="" style="display: none;" id="loading">
<script>
$('#btnUpload').on('click', function () {
// 转化为原生的对象
let files = $('#file1')[0].files
if (files.length <= 0) {
return alert('请选择文件后再上传!')
}
let fd = new FormData()
fd.append('avatar', files[0])
$.ajax({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/upload/avatar',
data: fd,
// 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
processData: false,
// 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
contentType: false,
success: function (res) {
console.log(res);
}
})
})
// 监听ajax请求,自 jQuery 版本 1.8 起,该方法只能被附加到文档
$(document).ajaxStart(function () {
$('#loading').show()
})
$(document).ajaxStop(function () {
$('#loading').hide()
})
</script>
</body>
</html>
10.6 axios
Axios是专注于网络数据请求的库,比原生的 XMLHttpRequest 对象,axios简单易用,比jQuery、axios更加轻量化,它只专注于网络数据请求
10.6.2 axios发起GET请求
axios.get('url', {params: {/*参数*/}}).then(callback)
10.6.2 axios发起POST请求
axios.post('url', {/*数据*/}).then(callback)
10.6.3 直接用axios发起请求
axios({
method: '请求类型',
url: '请求的URL地址',
data: {/* POST数据 */},
params: {/* GET参数 */}
}).then(callback)
10.6.4 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>axios</title>
<script src="js/axios.js"></script>
</head>
<body>
<button id="btn1">发起GET请求</button>
<button id="btn2">发起POST请求</button>
<button id="btn3">直接使用ajax发起GET请求</button>
<button id="btn4">直接使用ajax发起POST请求</button>
<script>
document.querySelector('#btn1').addEventListener('click', function() {
let url = 'http://www.liulongbin.top:3006/api/get'
let paramsObj = {name: 'ss', age: 20}
axios.get(url, {params: paramsObj}).then(function(res) {
console.log(res);
console.log(res.data);
})
})
document.querySelector('#btn2').addEventListener('click', function() {
let url = 'http://www.liulongbin.top:3006/api/post'
let dataObj = {address: '北京', location: '顺义区'}
axios.post(url, dataObj).then(function(res) {
console.log(res);
console.log(res.data);
})
})
document.querySelector('#btn3').addEventListener('click', function() {
let url = 'http://www.liulongbin.top:3006/api/get'
let paramsObj = {name: 'ss', age: 20}
axios({
method: 'GET',
url: url,
params: paramsObj
}).then(function(res) {
console.log(res);
console.log(res.data);
})
})
document.querySelector('#btn4').addEventListener('click', function() {
let url = 'http://www.liulongbin.top:3006/api/post'
let dataObj = {address: '北京', location: '顺义区'}
axios({
method: 'POST',
url: url,
params: dataObj
}).then(function(res) {
console.log(res);
console.log(res.data);
})
})
</script>
</body>
</html>
十一、跨域与JSONP
11.1 了解同源策略和跨域
同源策略是浏览器提供的一个安全功能
两个页面的协议,域名和端口都相同,则两个页面具有相同的源,即同源,反之为跨域
11.1.1 跨域
跨域拦截
跨域数据请求
JSONP:早期临时方案,只支持GET请求,和Ajax没有关系
CORS:两种都可以,不兼容低版本浏览器
11.2 JSONP
实现原理:JSONP通过
<script>
// $.ajax({
// method: 'GET',
// url: 'http://ajax.frontend.itheima.net:3006/api/jsonp',
// data: {
// name: 'ss',
// age: 20
// },
// success: function(res) {
// console.log(res);
// }
// })
function success(data) {
console.log('调用成功!');
console.log(data);
}
</script>
// <script src="js/getdata.js?callback=success"></script>
<script src="http://ajax.frontend.itheima.net:3006/api/jsonp?callback=success&name=ls&age=30"></script>
JQuery中的JSONP(ajax)
$.ajax({
url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
// 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
dataType: 'jsonp',
jsonp: 'ss',
jsonpCallback: 'hh',
success: function(res) {
console.log(res);
}
})
自动携带:callback=jQueryxxx,jQueryxxx随机生成的回调函数名称
JQuery中的JSONP过程
- 在发起JSONP请求的时候,动态向
中append一个
11.3 案例-淘宝搜索
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>淘宝搜素</title>
<!-- 导入页面的基本样式 -->
<link rel="stylesheet" href="css/search.css" />
<!-- 导入 jQuery -->
<script src="js/jquery.min.js"></script>
<!-- 导入模板引擎 -->
<script src="js/template-web.js"></script>
</head>
<body>
<div class="container">
<!-- Logo -->
<img src="images/taobao_logo.png" alt="" class="logo" />
<div class="box">
<!-- tab 栏 -->
<div class="tabs">
<div class="tab-active">宝贝</div>
<div>店铺</div>
</div>
<!-- 搜索区域(搜索框和搜索按钮) -->
<div class="search-box">
<input id="ipt" type="text" class="ipt" placeholder="请输入要搜索的内容" /><button class="btnSearch">搜索</button>
</div>
<!-- 搜索建议列表 -->
<div id="suggest-list"></div>
</div>
</div>
<!-- 模板结构 -->
<script type="text/html" id="tpl-suggestList">
{{each result}}
<div class="suggest-item">{{$value[0]}}</div>
{{/each}}
</script>
<script>
$(function () {
// 1、定义防抖的延时器 timer
var timer = null;
// 定义全局缓存对象
var cacheObj = {};
// 定义防抖函数,延时500毫秒后,再请求数据接口
function debounceSearch(kw) {
// 开启延时器
timer = setTimeout(function () {
getSuggestList(kw);
}, 500)
}
// 为输入框绑定Keyup事件
$('#ipt').on('keyup', function () {
// 清空timer
clearTimeout(timer);
var keywords = $(this).val().trim();
if (keywords.length <= 0) {
// 如果用户没有输入内容,则退出并清空隐藏列表
return $('#suggest-list').empty().hide()
}
// 发起请求之前,先判断缓存里是否有数据
if (cacheObj[keywords]) {
return renderSuggestList(cacheObj[keywords]);
}
// TODO:获取搜索建议列表
// console.log(keywords);
// 调用自定义函数
// getSuggestList(keywords);
debounceSearch(keywords);
})
// 获取搜索建议的函数封装
function getSuggestList(kw) {
$.ajax({
url: 'https://suggest.taobao.com/sug?q=' + kw,
// 发起JSONP请求
dataType: 'jsonp',
success: function (res) {
renderSuggestList(res);
}
})
}
// 渲染UI结构
// 传入一个res参数(res就是待渲染的数据)
function renderSuggestList(res) {
// 判断是否有待渲染的数据,如果没有就return出去,清空列表并隐藏
if (res.result.length <= 0) {
return $('#suggest-list').empty().hide();
}
// 调用模板引擎的template函数
var htmlstr = template('tpl-suggestList', res); // 返回一个渲染好的html结构
// 将渲染好的字符串放到搜索建议列表div中,并展示出来
$('#suggest-list').html(htmlstr).show();
// 1、获取到用户输入的内容,当做键
var k = $('#ipt').val().trim();
// 2、将数据做为值缓存到全局对象中
cacheObj[k] = res;
}
})
</script>
</body>
</html>
11.4 防抖和节流
防抖策略是当事件被触发后,延迟n秒后再执行回调,如果在这n秒内事件又被触发,则重新计时。
节流策略,可以减少一段时间内事件触发频率。
鼠标跟随节流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>鼠标跟随节流</title>
<script src="js/jquery.min.js"></script>
<style>
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
#angle {
position: absolute;
}
</style>
</head>
<body>
<img src="images/angle.gif" alt="" id="angle">
<script>
$(function() {
// 1.获取图片
var angle = $('#angle');
var timer = null; // 步骤1:定义节流阀
// 2.绑定mousemove事件
$(document).on('mousemove', function(e) {
// 步骤3:判断节流阀是否为空
if (timer) {
return;
} else {
// 步骤2:开启延时器
timer = setTimeout(function() {
$(angle).css('top', e.pageY + 'px').css('left', e.pageX + 'px');
console.log('ok');
timer = null;
}, 16);
}
});
});
</script>
</body>
</html>
十二、HTTP协议加强
12.1 HTTP协议简介
什么是http协议?
- 超文本传输协议
http协议规定了什么?
- 规定了客户端和服务器交互数据的时候,数据要遵守的格式。
- 请求/响应 模式
12.2 http请求消息/请求报文
请求报文,指的是客户端提交给服务器的全部数据。
- 请求行
- 请求方式
- 请求url地址
- 协议及版本
- 请求头
- 键:值 的形式,一次请求,可能会有很多请求头
- Content-Type: ‘application/x-www-form-urlencoded’ / ‘multipart/form-data; xxx’
- 提交的数据的一种编码格式(查询字符串格式 / FormData格式)
- User-Agent: ‘’
- 体现了当前客户端是什么浏览器、版本是什么版本
-
空行
- 分隔作用
-
请求体
- xhr.send(请求体); 客户端提交的数据就是请求体
- GET方式没有请求体
- POST方式 才有请求体
12.3 http响应消息/响应报文
-
响应行
- 协议及版本
- http状态码 (比如, 200)
- http状态描述信息 (比如, OK)
-
响应头
-
Access-Control-Allow-Origin: ‘*’
- CORS跨域资源共享,服务器设置的响应头,允许ajax跨域
-
Content-Type: ‘application/json; charset=utf-8’
-
服务器告诉客户端,返回的数据是什么格式的,编码是什么编码
$.get(url, data, callback, dataType); - dataType 表示预期服务器返回的类型 jQuery如何知道服务器返回的数据类型呢?是根据响应头中的Content-Type判断,如果判断服务器返回的是json格式,所以jQuery内部就会自动调用JSON.parse()将JSON格式的数据转成JS数组或对象 $.get(url, data, function (res) { 如果响应头没有没有Content-Type,则res 就是字符串 手动指定最后一个dataType为json之后,res就是JS对象 });
-
-
-
空行
- 分隔作用
-
响应体
- 服务器返回的主体内容。
- 就是我们之前所说的,服务器返回的数据。
12.4 请求方式
12.5 http响应状态码
- 200(OK)表示请求成功
- 201(Created)请求成功,一般用于添加资源成功
- 304 (Not Modified)表示请求的资源没有修改(第一次请求)
- 400(Bad Request)语法有误(一般来说,请求参数写错了或者请求头写错了)
- 403(Forbidden)访问成功了,但是服务器告诉你没有权限访问
- 404(Not Found)请求的资源,在服务器上不存在,找不到。
- 500()服务器内部错误