服务器相关概念
服务器 : 上网过程中,负责 存放或对外提供资源 的电脑,叫做服务器
客户端 : 在上网过程中,负责 获取和消费资源 的电脑,叫做客户端
URL(全称是 UniformResourceLocator
) 中文叫 统一资源定位符,用于标识互联网上每个资源的唯一存放位置。浏览器只有通过URL地址,才能正确定位资源的存放位置,从而成功访问到对应的资源
URL地址一般由三部分组成:
协议 , 主机名 , 端口号 , 路径
端口号
端口号 80 可以省略不写
客户端与服务器之间的通讯过程,分为: 请求-处理-响应 三个步骤
客户端请求服务器时,请求的方式 有很多种,最常见的两种请求方式分别是 get
和 post
请求
get 请求
,通常用于 获取服务器资源(要资源)例如:根据 URL
地址,从服务器获取 HTML
文件、css
文件、js
文件、图片文件、数据资源等。
post 请求
,通常用于 向服务器提交数据(送资源)例如:登录时,向服务器 提交登录信息、注册时向服务器 提交注册信息、添加用户时向服务器 提交用户信息等各种 数据提交操作
(1)通过地址栏发送请求
(2)通过表单发送请求
(3)通过ajax对象发送请求
Ajax
的全称是 Asynchronous JavaScript And XML
(异步 JavaScript
和 xml
)
通俗理解:在网页中利用 XMLHttpRequest
(是DOM 内置的一个API )对象和服务器进行数据交互的方式,就是Ajax
。
之前所学的技术,只能把网页做的更美观漂亮 ,或添加一些动画效果,但还是,Ajax能让我们轻松实现 网页 与 服务器之间的 数据交互
场景一:用户名检测 : 检测用户名是否被占用
场景二:搜索提示 : 动态 加载搜索提示列表
场景三:数据无刷新分页显示 : 根据页码值动态刷新表格的数据
场景四:数据的无刷新增删改查 : 数据的添加、删除、修改、查询操作
浏览器中提供的 XMLHttpRequest
用法比较复杂,所以 jQuery
对 XMLHttpRequest
进行了封装,提供了一系列Ajax相关的函数,极大地 降低了Ajax的使用难度
jQuery
中发起 Ajax 请求最常用的三个方法如下:
$.get()
get方式请求,用于**获取(下载)**数据$.post()
post方式请求,用于提交(上传)数据$.ajax()
比较综合,既可以获取数据,又可以提交数据**(获取&提交)**url 地址错误
用于**获取(下载)**数据
get
请求,从而将服务器上的资源请求到客户端来进行使用
$.get(url,[data],[callback]) []:可选参数
**使用 $.get() 函数 发起不带参数的请求时,直接提供给 **请求的 URL 地址 和 请求成功之后的回调函数 即可
$(function () {
$.get("http://www.liulongbin.top:3006/api/getbooks", function (res) {
console.log(res);
});
});
使用$.get()
发起携带参数的请求,那么携带的参数应该写在第二个参数的位置
$(function () {
$.get("http://www.liulongbin.top:3006/api/getbooks", { bookname: "三国演义", author: "罗贯中" }, function (res) {
console.log(res);
});
});
用于提交(上传)数据
$(function () {
$("button").on("click", function () {
$.post(
"http://www.liulongbin.top:3006/api/addbook",
{
bookname: "啊飞的一天",
author: "阿飞",
publisher: "黑马",
},
function (res) { // 成功后的回调函数
console.log(res);
}
);
});
});
$.ajax() 注意事件
只需要将 type
属性 的值设置为 ‘GET
’ 即可
// ajax-不带参数请求
$("#btn1").on("click", function () {
$.ajax({
type: "get",
url: "http://www.liulongbin.top:3006/api/getbooks",
data: {},
success: function (res) {
console.log(res);
},
});
});
// -----------------------------
// ajax - 携带参数请求;
$("#btn2").on("click", function () {
console.log(11);
$.ajax({
type: "get",
url: "http://www.liulongbin.top:3006/api/getbooks",
data: { bookname: "三国演义" },
success: function (res) {
console.log(res);
},
});
});
只需要把 type
属性的值 设置为 ‘post
’ 即可
// ajax-post请求
$("#btn3").on("click", function () {
$.ajax({
type: "post",
url: "http://www.liulongbin.top:3006/api/addbook",
data: {
bookname: "程序员自我修养",
author: "阿飞",
publisher: "黑马",
},
success: function (res) {
console.log(res);
},
});
});
});
使用 Ajax
请求数据时,被请求的 URL
地址,就叫做 数据接口(简称接口)。同时,每个接口必须有请求方式。
例如:
http://www.liulongbin.top:3006/api/getbooks 获取图书列表的接口(get请求)
http://www.liulongbin.top:3006/api/addbook 添加图书的接口(post请求)
ajax课程的在线接口文档:https://www.showdoc.com.cn/ajaxapi?page_id=3753323218792173
接口的说明文档,它是我们调用接口的依据。好的接口文档包含了对 接口URL,参数 以及 输出内容 的说明,我们参照接口文档就能方便的知道接口的作用,以及接口如何进行调用
为了验证接口是否被正常被访问,我们常常需要使用接口测试工具,来对数据接口进行检测
**好处:**接口测试工具能让我们在 不写任何代码 的情况下,对接口进行 调用 和 测试
常用的就是:PostMan
PostMan
测试GET接口PostMan
测试POST接口url 地址错误
Cannot GET/api/addbook 请求地址 , 请求方式错误
UI
界面搭建需要使用到的库和插件
css
库 bootstrap.css
javascript
库 jquery.js
vs code
插件 Bootstrap 3 Snippets
搭建步骤
bs3-panel:primary
)panel-body
里面,创建3个对应的输入框 (快捷键:bs3-input:addon:text
),对应修改标题panel-body
最后面,创建 button
按钮 (快捷键:bs3-button:primary
),修改内容bs3-table:bordered
)td
,填写里面内容内联表单
为 元素添加
.form-inline
类可使其内容左对齐并且表现为 inline-block
级别的控件。
ajax课程的在线接口文档:https://www.showdoc.com.cn/ajaxapi?page_id=3753323218792173
步骤:
创建入口函数
url
,和成功之后的回调函数 // [1] 渲染列表
getBookList();
function getBookList() {
// (1)调接口,获取所有的图书馆数据
$.ajax({
type: "get",
url: "http://www.liulongbin.top:3006/api/getbooks",
success: function (res) {
// (2) 判断数据是否获取成功
if (res.status !== 200) {
return alert("获取图书失败");
}
// (3) 把数据遍历渲染到页面
// 遍历数据,生成tr
var rows = [];
res.data.forEach(function (item, index, array) {
var newStr = `
${item.id}
${item.bookname}
${item.author}
${item.publisher}
${item.id}>删除
`;
// 把遍历出来的数据 追加到空数组里
rows.push(newStr);
});
// 添加到tbody中
// 性能优化去掉字符串拼接
$("tbody").html(rows.join(""));
},
});
}
tbody
容器,通过事件委派的方式,给动态创建的a
标签绑定事件id
删除,所以我们需要得到对应的id
,我们利用自定义属性的方式,传递过来相应的id
// [2] 删除功能
// (1) 给删除按钮绑定单击事件 (事件委托,动态检测)
// (2) 获取被删图书的 id
// 1) 渲染列表时,给删除添加自定义属性 data-id
// 2) 获取自定义属性的值 $(this).attr(data-id)
// (3) 询问是确定删除 if(confirm) // true false
// (4) 调接口
// (5) 判断是否删除成功,成功后重新渲染列表
$("tbody").on("click", ".del", function () {
var id = $(this).attr("data-id"); // 获取自定义属性的值
if (confirm("确定要删除")) {
$.ajax({
type: "get",
url: "http://www.liulongbin.top:3006/api/delbook",
data: { id: id },
success: function (res) {
if (res.status !== 200) {
return alert(res.msg);
}
getBookList();
},
});
}
});
// [3] 添加功能
// (1) 给添加按钮绑定单击事件
// (2) 收集数据
// (3) 判断数据是否合法(不能为空)
// (4) 调接口 ,添加图书
// (5) 判断是否添加成功 , 如果成功重新渲染页面
$("#btnAdd").on("click", function () {
var bookname = $("#iptBookname").val().trim();
var author = $("#iptAuthor").val().trim();
var publisher = $("#iptPublisher").val().trim();
if (bookname === "" || author === "" || publisher === "") {
return alert("值不能为空");
}
// if (bookname.leng <= 0 || author.length <= 0 || publisher.length <= 0) {
return alert("值不能为空");
}
$.ajax({
type: "post",
url: "http://www.liulongbin.top:3006/api/addbook",
data: {
bookname: bookname,
author: author,
publisher: publisher,
},
success: function (res) {
if (res.status !== 201) {
return alert(res.msg);
}
getBookList();
$("#iptBookname").val("");
$("#iptAuthor").val("");
$("#iptPublisher").val("");
},
});
});
UI
结构梳理
业务代码抽离
resetui()
函数作用-让聊天框区域自动滚动到底部
ajax课程的在线接口文档:https://www.showdoc.com.cn/ajaxapi?page_id=3753323218792173
ul
容器,调用 append
函数来追加 li
,注意:追加li
的类名叫做 right_word
resetui()
,让聊天框区域自动滚动到底部 // [1] 单击发送 , 把聊天消息渲染到页面
$("#btnSend").on("click", function () {
var text = $("#ipt").val().trim(); // 1.获取输入框的信息
console.log(text);
// 判断输入框是否为空 // if (text==="")
// if (!text) return;
if (text.length <= 0) {
return;
}
// 2.信息渲染到页面
// 新建li
var newLi = `
${text}
`;
$("#talk_list").append(newLi);
resetui(); // 滚动条滚动到最新位置
$("#ipt").val(""); // 清空输入框
//[2] 向机器人发送消息(调接口),机器人回复
getMsg(text);
});
getMsg()
接收一个参数,参数就是用户发送的信息$.ajax()
发送一个 GET 方式请求,传入请求地址 http://www.escook.cn:3006/api/robot
spoken:value
success
成功的回调,在回调函数里面判断返回数据的 message
是否等于 success
// [2]封装一个函数 专门向机器人发送消息,渲染回复语
// 1.把输入框内容发送给机器人
function getMsg(text) {
$.ajax({
type: "get",
url: "http://www.liulongbin.top:3006/api/robot",
data: { spoken: text },
success: function (res) {
console.log(res);
if (res.message == "success") {
console.log("机器人回复了", res.data.info.text);
// 把机器人的回复,渲染到页面
// 新建对话框 li
var newLi = `
${res.data.info.text}
`;
$("#talk_list").append(newLi);
resetui(); // 滚动条滚动最新位置
getVoice(res.data.info.text); // [3] 把机器人的文字消息转成语音
}
},
});
}
封装函数 getVoice()
接收一个参数,机器人的聊天信息
利用 $.ajax()
发送一个 GET 方式请求,传入请求地址 http://ajax.frontend.itheima.net:3006/api/synthesize
定义请求数据 text:value
定义success
成功的回调,判断返回的状态码是否是200,如果是代表成功
在页面上定义 audio
标签,设置隐藏,等数据返回之后,利用这个 audio
来进行播放。设置 autoplay
属性来进行自动播放
结构里面加一个音频标签把获取到的src地址赋值进去播自动放音频
<audio src="" id="voice" autoplay style="display: none;">audio>
// 2.封装一个函数,专门把机器人回复的文字转成语音
function getVoice(text) {
// 调接口
$.ajax({
text: "get",
url: "http://www.liulongbin.top:3006/api/synthesize",
data: { text: text },
success: function (res) {
console.log(res);
if (res.status === 200) {
// console.log(res.voiceUrl)
// 给音频标签设置src
$("#voice").attr("src", res.voiceUrl);
}
},
});
}
keyup
事件,按键弹起的事件监听keycode
来获取对应的按键的 机器码keycode
是否等于 13(不需要去记忆,开发时候打印调试一下就行了),如果是,代表是回车键$('#btnSend').click()
// [4]在输入框中敲回车,就能发送消息
// 为输入框框绑定 keyup 事件
$("#ipt").on("keyup", function (e) {
// 判断键值
if (e.keyCode === 13) {
// 触发“发送”按钮的click事件
$("#btnSend").click();
}
});
表单在网页中主要负责 数据采集功能 并把采集的信息提交到服务器端进行处理
type
属性为submit
来触发form
表单的提交 , 通过设置属性 值为 reset
来重置表单
标签的属性(⭐⭐⭐)action
属性用来规定当提交表单时,向何处发送表单数据。
表单在没有设置 action
属性或 action
值为空下,action
的默认值为当前页面的 URL
地址注意: 当提交表单后,会立即跳转到 action
属性指定的 URL
地址
target
属性用来规定 在何处打开 action URL
_blank
在新窗口打开_self
在相同窗口打开method
属性用来规定 以何种提交方式 把表单数据提交到 action URL
它的可选值有两个,分别是 get
和 post
默认情况下,method
的值为 get
, 表示通过URL
地址的形式,把表单数据提交到 action URL
注意:
enctype
属性用来规定在 发送表单数据之前如何对数据进行编码
注意:
在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data表单的同步提交及缺点
通过点击 submit 按钮,触发表单提交的操作,从而使页面跳转到 action URL
的行为,叫做表单的同步提交
表单同步提交后,整个页面会发生跳转,跳转到 action URL 所指向的地址,用户体验很差
表单同步提交后,页面之前的状态和数据会丢失解决方案
表单只复杂采集数据,Ajax负责将数据提交到服务器
在 jQuery
中,可以使用如下两种方式,监听到表单的提交事件 submit
, 会跳转页面
$("#form").submit(function () {
alert(1);
});
$("#form").on("submit", function () {
alert(1);
});
$("#form").submit(function (e) {
e.preventDefault();
});
$("#form").on("submit", function (e) {
e.preventDefault();
});
serialize()
函数
serialize() 函数的好处:可以一次性获取到表单中的所有的数据。键值对字符串
注意: 一定要给表单设置 name
属性 , 否则收集不到数据
$("#form").serialize();
具体实现步骤
$("#form").submit(function (e) {
e.preventDefault();
var data = $(this).serialize();
console.log(data);
$.ajax({
method: "post",
url: "http://www.liulongbin.top:3006/api/addbook",
data: data,
success: function (res) {
console.log(res);
},
});
});
使用到的技术方案[ form + ajax ]
UI
结构搭建步骤
bs3-panel:primary
)bs3-button:primary
)list
列表(快捷键:bs3-list-group
)li
里面放两个 span
,写入 评论时间和评论人getCommentList()
url
,是否需要携带参数,请求方式$.ajax()
来进行请求success
回调函数中,判断请求数据是否成功,如果状态码不是200,提示用户 getCommentList();
// [1] 获取评论 ,渲染页面
function getCommentList() {
// 发送 ajax 请求 获取数据
$.ajax({
url: "http://www.liulongbin.top:3006/api/cmtlist",
success: function (res) {
console.log(res);
// 判断请求是否成功
if (res.status !== 200) alert("获取失败");
// 渲染数据到页面
},
});
rows
),用来存放每一个元素的html
字符串结构html
字符串结构,然后放入到数组中 // 渲染数据到页面
var rows = [];
res.data.forEach((item) => {
var newLi = `
评论时间:${item.username}
评论人:${item.time}
${item.content}
`;
rows.push(newLi);
});
$("#cmt-list").html(rows.join(""));
},
panel-body
的标签改成 form
标签name
属性,name属性的值最好与接口文档定义的参数名称一致sumbit
事件,阻止表单提交的默认行为serialize()
)示例代码
$(function () {
$('#formAddCmt').submit(function (e) {
e.preventDefault(); // 阻止默认行为
var data = $(this).serialize(); // 收集表单数据
})
})
})
$.post()
发送请求,传入数据status
是否是201,如果是代表成功,失败进行提示getCommentList()
),清空表单内容($('#formAddCmt')[0].reset()
)示例代码
$("#myForm")[0].reset() 方法可把表单中的元素重置为它们的默认值
// [2] 发表评论
$("#formAddCmt").submit(function (e) {
e.preventDefault(); // 阻止默认行为
var data = $(this).serialize(); // 收集表单数据
// ajax 发送请求
$.ajax({
method: "post",
url: "http://www.liulongbin.top:3006/api/addcmt",
data: data,
success: function (res) {
console.log(res);
if (res.status !== 201) return "添加失败";
getCommentList(); // 重新渲染页面
// document.querySelector("#formAddCmt").reset();
$("#formAddCmt")[0].reset();
},
});
});
之前在渲染UI
结构时候,拼接字符串是比较麻烦的,而且很容易出现问题
模板引擎,它可以根据程序员指定的 模板结构 和 数据,自动生成一个完整的HTML页面
art-template 是一个简约,超快的模板引擎,中文官首页:http://aui.github.io/art-template/zh-cn/index.html
art-template的使用步骤
① 导入 art-template
② 定义数据
③ 定义模板
④ 调用 template 函数
⑤ 渲染HTML结构
导入 art-template
<script src="./lib/template-web.js"></script>
定义数据
var data = { name: 'zs', age: 20}
定义模板
script
标签中,注意:需要把type属性改成 text/html
id
name
属性的值<script type="text/html" id="tpl-user">
<h1>{{name}} ------ {{age}}</h1>
script>
调用 template
函数 , 自动生成 html 字符串
var htmlStr = template('tpl-user', res)
渲染HTML
结构
$('#container').html(htmlStr)
代码示例
{{ }} 占位
{{each 数组}}
{{$value}}
{{/each}}
<!-- 3.定义模版 -->
<script type="text/html" id="tpl">
<p>{{ name }}</p>
<p>{{ dog.color }}</p>
<p>{{ age > 18 ? "成年" : "未成年"}}</p>
<p>{{ age-3 }}</p>
<div>{{@ title}}</div>
</script>
<script src="./lib/jquery.js"></script>
<!-- 1.导入 art-template -->
<script src="./lib/template-web.js"></script>
<script>
// 2.定义数据
var data = {
name: "zs",
age: 19,
title: "我是h1标签
",
dog: {
color: "red",
},
};
// 3.调用模版
var htmlStr = template("tpl", data);
console.log(htmlStr);
// 4.渲染HTML结构
$("#box").html(htmlStr);
art-template 提供了 {{}} 这种语法格式,在 {{}} 内可以进行 变量输出 或 循环数组 等操作,这种 {{}} 语法在 art-template 中被称为标准语法(模板语法)
{{value}}
{{obj.key}}
{{obj['key']}}
{{a ? b : c}}
{{a || b}}
{{a + b}}
在 {{ }} 语法中,可以进行变量的输出、对象属性的输出、三元表达式输出、逻辑或输出、加减乘除等表达式输出。
{{@ value }}
如果要输出的 value 值中,包含了 HTML 标签结构,则需要使用原文输出语法,才能保证 HTML 标签被正常渲染。
{{if value}} 按需输出的内容 {{/if}}
{{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}
如果要实现条件输出,则可以在 {{ }} 中使用 if … else if … /if 的方式,进行按需输出。
{{each arr}}
{{$index}} {{$value}}
{{/each}}
如果要实现循环输出,则可以在 {{ }} 内,通过 each 语法循环数组,当前循环的索引使用 $index 进行访问,当前的循环项使
用 $value 进行访问。
过滤器的本质,就是一个 function 处理函数。
渲染一个变量的值 , 处理变量的格式
语法
{{$value.time|dateFormat}}
过滤器语法类似于 管道操作符,它的上一个输出作为下一个输入 , 把 {{$value}.time} (需要处理的值)传给过滤函数
定义过滤器的基本语法如下:
template.defaults.imports.dateFormat = function (val){/*return处理的结果*/}
// 在模板引擎中使用过滤器
<h2>{{msg|toUp}}</h2>
// 定义大小写函数
template.defaults.imports.toUp = function (val) {
return val.toUpperCase();
};
定义格式化日期时间的过滤器函数
定义数据
var data = { regTime: new Date() }
定义过滤器
// 定义格式化日期时间的过滤器函数
template.defaults.imports.dateFormat = function (val) {
var dt = new Date(val);
var y = dt.getFullYear();
var m = dt.getMonth() + 1;
m = padZero(m);
var d = dt.getDate();
d = padZero(d);
var hh = dt.getHours();
hh = padZero(hh);
var mm = dt.getMinutes();
mm = padZero(mm);
var ss = dt.getSeconds();
ss = padZero(ss);
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
};
// 定义补零函数
function padZero(n) {
return n < 10 ? `0${n}` : n;
}
在模板引擎中使用过滤器
<script type="text/html" id="tpl-user">
<h3>{{regTime | dateFormat}}</h3>
script>
item
模板text/html
,给模板定义idart-template的使用步骤
① 导入 art-template
② 定义数据
③ 定义模板
④ 调用 template 函数
⑤ 渲染HTML结构
模板代码
<div id="news-list"></div>
<!-- 定义模板 -->
<script type="text/html" id="tpl">
{{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.split(",")}}
<span>{{$value}}</span>
{{/each}}
</div>
<div class="footer">
<div>
<span>胡润百富</span>
<span> {{$value.time|dateFormat}} </span>
</div>
<span> {{ $value.cmtcount }} </span>
</div>
</div>
</div>
{{/each}}
</script>
js代码
// [1] 获取新闻数据渲染到页面
getNewsList();
function getNewsList() {
// 发送ajax 请求,获取数据
$.ajax({
url: "http://www.liulongbin.top:3006/api/news",
success: function (res) {
console.log(res);
// 判断请求是否成功
if (res.status !== 200) return "获取数据失败";
// [2]渲染到页面
// 1.引入js
// 2.准备数据
// 3.准备模版
// 4.调用templat
var htmlStr = template("tpl", res); // res 对象
// 5.渲染数据到页面
$("#news-list").html(htmlStr);
},
});
}
// 定义格式化日期时间的过滤器函数
template.defaults.imports.dateFormat = function (val) {
var dt = new Date(val);
var y = dt.getFullYear();
var m = dt.getMonth() + 1;
m = padZero(m);
var d = dt.getDate();
d = padZero(d);
var hh = dt.getHours();
hh = padZero(hh);
var mm = dt.getMinutes();
mm = padZero(mm);
var ss = dt.getSeconds();
ss = padZero(ss);
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
};
// 定义补零函数
function padZero(n) {
return n < 10 ? "0" + n : n;
}
<!-- 模版引擎 -->
<script type="text/html" id="tpl">
{{each data}}
<tr>
<td>{{$value.id}}</td>
<td>{{$value.bookname}}</td>
<td>{{$value.author}}</td>
<td>{{$value.publisher}}</td>
<td><a href="javascript:;" class="del" data-id="{{$value.id}}">删除</a></td>
</tr>
{{/each}}
</script>
// [1]渲染数据到表格
getBookList();
function getBookList() {
$.ajax({
type: "get",
url: "http://www.liulongbin.top:3006/api/getbooks",
success: function (res) {
console.log(res);
if (res.status !== 200) {
return alert("图书获取失败");
}
var htmlStr = template("tpl", res); // 4.调用template函数
// console.log(htmlStr)
$("#tb").html(htmlStr); // 5.渲染数据到页面
},
});
}
注意 : data 选项的值有两种 ⭐️⭐️⭐️
$("#Form").on("submit", function (e) {
e.preventDefault(); // 阻止默认行为
var data = $(this).serialize(); // 获取表单数据
console.log(data);
// if ($("#Bookname").val().length <= 0 || $("#Author").val().length <= 0 || $("#Publisher").val().length <= 0)
// return alert("不能为空");
var dataArr = data.split("&"); // 截取成数组
for (var i = 0; i < dataArr.length; i++) {
var Karr = dataArr[i].split("="); // 数组在继续分割
if (karr[1] === "null" || Karr[1] === "") {
return alert("值不能为空");
}
}
// ajax 发送请求
$.ajax({
method: "post",
url: "http://www.liulongbin.top:3006/api/addbook",
data: data, // 可以是对象,可以是键值对
success: function (res) {
// console.log(res);
if (res.status !== 201) {
return alert("添加失败");
}
getBookList(); // 渲染
$("#Form")[0].reset(); // 清空
},
});
});
作用 : 指定的字符串中进行正则搜索
正则与字符串操作
exec()
函数用于 检索字符串 中的正在表达式的匹配
如果字符串中有匹配的值,则返回该匹配值,否则返回 null
示例代码如下:
正则表达式中 () 包起来的内容表示一个分组,可以通过分组来 提取自己想要的内容,示例代码如下
replace() 函数用于在字符串中 用一些字符 替换 另一些字符的
步骤
xhr
对象 newxhr.open()
函数 , 设置请求方式和地址xhr.send()
函数 , 发送请求xhr.onreadystatechange
事件 // 1.创建 ajax 对象
var xhr = new XMLHttpRequest();
// 2.设置请求方式和地址
xhr.open("get", "http://www.liulongbin.top:3006/api/getbooks");
// 3.发送请求
xhr.send();
// 4.监听onreadystatechange 事件(设置服务响应后执行的函数)
xhr.onreadystatechange = function () {
// 判断请求是否完成
// readyState 表示当前ajax 请求处于什么阶段 , 4表明请求完成阶段
// status响应转态码
if (xhr.readyState == 4 && xhr.status == 200) {
// 获取服务器响应的数据---json字符串
console.log(xhr.responseText);
// join 字符串转转对象
var data = JSON.parse(xhr.responseText);
console.log(data);
}
};
请求转态和响应转态
XMLHttpRequest
对象的 readyState
属性,用来表示当前 Ajax
请求所处的状态。每个 Ajax
请求必然处于以
这种在 URL 地址后面拼接的参数,叫做查询字符串。所有get请求的参数格式都是查询字符串
$.get('http://www.liulongbin.top:3006/api/getbooks', { bookname: '三国演义', author: '罗贯中' }, function(res) {
console.log(res)
})
get请求参数的要求:
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1')
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
URL 编码: 就是使用英文字符去代替汉字等
**定义:**查询字符串(URL 参数)是指在 URL 的末尾加上用于向服务器发送信息的字符串(变量)。
**格式:**将英文的 ? 放在URL
的末尾,然后再加上 参数=值 ,想加上多个参数的话,使用 & 符号进行分隔。
步骤
创建 xhr
对象
调用 xhr.open()
函数 , 设置请求方式和请求地址
设置请求头设置 Content-Type 属性
调用 xhr.send()
函数,同时指定要发送的数据
监听 xhr.onreadystatechange
事件
post请求参数的格式
// 第1步,创建ajax对象
var xhr = new XMLHttpRequest()
// 第2步,设置请求方式和请求地址
xhr.open('post', 'http://www.liulongbin.top:3006/api/addbook')
// 第3步,设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 第4步,发送请求
xhr.send('bookname=老李的两天&author=laoli&publisher=heima')
// 第5步,监听onreadystatechange事件
xhr.onreadystatechange = function() {
// 判断请求是否成功
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
数据交换格式,就是服务器端与客户端之间进行数据传输与交换的格式
前端领域,经常提及的两种数据交换格式分别是 XML
和 JSON
。
HTML
被设计用来描述网页上的内容,是网页内容的载体
XML
被设计用来传输和存储数据,是数据的载体
概念:JSON
的英文全称是 JavaScript Object Notation
,即“JavaScript 对象的字符串表示法”。简单来讲,
JSON
的本质是字符串。
作用:JSON
是一种轻量级的文本数据交换格式,在作用上类似于 XML
,专门用于存储和传输数据,但
是 JSON
比 XML
更小、更快、更易解析。
JSON
就是用字符串来表示 Javascript
的对象和数组。所以,JSON
中包含对象和数组两种结构,通过这
对象结构在 JSON
中表示为 { }
括起来的内容。数据结构为 { key: value, key: value, … }
的键
值对结构。其中,key
必须是使用英文的双引号包裹的字符串,value
的数据类型可以是数字、字符串、
布尔值、null、数组、对象6种类型。
数组结构在 JSON
中表示为 [ ]
括起来的内容。数据结构为 [ "java", "javascript", 30, true … ]
。
数组中数据的类型可以是数字、字符串、布尔值、null、数组、对象6种类型。
① 属性名必须使用双引号包裹
② 字符串类型的值必须使用双引号包裹
③ JSON
中不允许使用单引号表示字符串
④ JSON
中不能写注释
⑤ JSON
的最外层必须是对象或数组格式
⑥ 不能使用 undefined
或函数作为 JSON
的值
**JSON
的作用:**在计算机与网络之间存储和传输数据。
JSON
的本质:用字符串来表示 Javascript
对象数据或数组数据
JSON
是 JS
对象的字符串表示法,它使用文本表示一个 JS
对象的信息,本质是一个字符串。例如:
要实现从 JSON
字符串转换为 JS
对象,使用 JSON.parse()
方法:
要实现从 JS
对象转换为 JSON
字符串,使用 JSON.stringify()
方法:
把对象转成json字符串—序列化操作----例子;把数组保存到本地存储!
var obj = { name: 'lisi', age: 20, hobby: ['吃饭', '睡觉', '打豆豆'] }
var str = JSON.stringify(obj)
console.log(str) // {"name":"lisi","age":20,"hobby":["吃饭","睡觉","打豆豆"]}
console.log(typeof str) // string
把json字符串转回对象—反序列化操作----例子:使用原生ajax获取到的图书数据就是json字符串。
var s = '{"name":"lisi","age":20,"hobby":["吃饭","睡觉","打豆豆"]}'
var o = JSON.parse(s)
console.log(o) // 可以展开的对象
Object
age: 20
hobby: (3) ['吃饭', '睡觉', '打豆豆']
name: "lisi"
[[Prototype]]: Object
JSON.parse() 应用
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
console.log(typeof xhr.responseText)
// JSON 字符串转 JOSN 对象 ===> 对象可以展开
var result = JSON.parse(xhr.responseText)
console.log(result)
}
}
配置对象中可以配置如下属性:
method
请求的类型url
请求的 URL
地址data
请求携带的数据success
请求成功之后的回调函数处理data参数
需要把 JSON 对象转 JSON 字符串 , data 里面接收的是字符串 , 程序员输入的是对象
/*** 处理 data 参数
* @param {data} 需要发送到服务器的数据
* @returns {string} 返回拼接好的查询字符串 name=zs&age=10
*/
function resolveData(data) {
var arr = []
for (var k in data) {
var str = k + '=' + data[k]
arr.push(str)
}
return arr.join('&')
}
定义 npAjax 函数
function npAjax(options) {
var xhr = new XMLHttpRequest()
// 把外界传递过来的参数对象,转换为 查询字符串
// 处理参数数据--从对象 =====> 键值对字符串(get和post请求参数的格式都是键值对)
var qs = resolveData(options.data)
// 注册监听
xhr.onreadystatechange = function () {
// 注册监听
if (xhr.readyState === 4 && xhr.status === 200) {
// 把服务器的json字符串转成js对象
var result = JSON.parse(xhr.responseText)
options.success(result)
}
}
}
判断请求的类型
不同的请求类型,对应 xhr
对象的不同操作,因此需要对请求类型进行 if … else …
的判断:
if (options.method.toUpperCase() === 'GET') {
// 发起GET请求
xhr.open(options.method, options.url + '?' + qs)
xhr.send()
} else if (options.method.toUpperCase() === 'POST') {
// 发起POST请求
xhr.open(options.method, options.url)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(qs)
}
// 封装一个函数---发送ajax请求的
function npAjax (options) {
// 配置对象 {method:'',url:'',data:{},success: function(){}}
// console.log(options)
// 创建ajax对象
var xhr = new XMLHttpRequest()
// 处理参数数据--从对象 =====> 键值对字符串(get和post请求参数的格式都是键值对)
var qs = resolveData(options.data)
// console.log(qs)
// 判断请求方式
if (options.method.toUpperCase() === 'GET') {
// console.log('发送get请求')
xhr.open('GET', options.url + '?' + qs)
xhr.send()
} else if (options.method.toUpperCase() === 'POST') {
// console.log('发送post请求')
xhr.open('POST', options.url)
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-url-encoded')
xhr.send(qs)
}
// 监听onreadystatechange事件了
xhr.onreadystatechange = function () {
// 判断请求是否成功
if (xhr.readyState === 4 && xhr.status === 200) {
// console.log('请求成功了')
// console.log('服务器响应的数据是', xhr.responseText)
// 把服务器响应的json字符串,转回对象
var data = JSON.parse(xhr.responseText)
// console.log(data)
// 执行成功之后的回调函数
options.success(data)
}
}
}
function resolveData (obj) {
// { bookname: '三国演义', author: '罗贯中' }
// 'bookname=三国演义&author=罗贯中'
var str = ''
// 遍历对象 for in
for (var k in obj) {
str += '&' + k + '=' + obj[k]
}
str = str.substring(1) // 从索引为1开始截 , 返回新的字符串
return str
}
浏览器提供了 URL
编码与解码的 API
,分别是:
encodeURI()
编码的函数decodeURI()
解码的函数可以设置 HTTP 请求的时限
可以使用 FormData
对象管理表单数据
可以上传文件
可以获得数据传输的进度信息
<script>
// 创建ajax对象
var xhr = new XMLHttpRequest()
// 设置请求方式和请求地址
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
// 设置 超时时间
xhr.timeout = 30
// 设置超时以后的处理函数
xhr.ontimeout = function () {
console.log('请求超时了!')
}
// 发送请求
xhr.send()
// 监听onreadystatechange事件
xhr.onreadystatechange = function () {
// 判断请求是否成功
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
</script>
// 1. 新建 FormData 对象
var fd = new FormData()
// 2. 为 FormData 添加表单项 // .append(键, 值)
fd.append('uname', 'zs')
fd.append('upwd', '123456')
// 3. 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 4. 指定请求类型与URL地址
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 把formdata对象放入send()方法中
// 数据是formdata格式,不要设置请求头
xhr.send(fd)
// 监听onreadystatechange事件
xhr.onreadystatechange = function () {
// 判断请求是否成功
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
// 获取表单元素
var form = document.querySelector('#form1')
// 监听表单元素的 submit 事件
form.addEventListener('submit', function(e) {
// 阻止默认提交行为
e.preventDefault()
// 收集数据---formdata对象来收集
// var fd = new FormData(表单对象)
// 根据 form 表单创建 FormData 对象,会自动将表单数据填充到 FormData 对象中
var fd = new FormData(form)
// 创建ajax对象
var xhr = new XMLHttpRequest()
// 设置请求方式和请求地址
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 把formdata对象放入send()方法中
// 数据是formdata格式,不要设置请求头
xhr.send(fd)
// 监听onreadystatechange事件
xhr.onreadystatechange = function() {
// 判断请求是否成功
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
})
如果数据是formdata对象,那么在使用$.ajax()提交数据时,需要额外的配置
// 使用formdata对象模拟数据
var fd = new FormData();
fd.append("uname", "laoli");
fd.append("upwd", "aoe1234");
$.ajax({
method: "post",
url: "http://www.liulongbin.top:3006/api/formdata",
// data: {}
data: fd,
// 不需要设置请求头!
contentType: false,
// 默认会把data中的数据转成键值对字符串,但是此时不需要转
processData: false,
success: function (res) {
console.log(res);
},
});
新版 XMLHttpRequest
对象,不仅可以发送文本信息,还可以上传文件。
实现步骤:
① 定义 UI
结构
② 验证是否选择了文件
③ 向 FormData
中追加文件
④ 使用 xhr
发起上传文件的请求
⑤ 监听 onreadystatechange
事件
<input type="file" id="file1" />
<button id="btnUpload">上传文件button>
<br />
<img src="" alt="" id="img" width="800" />
https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/file
// 1. 获取上传文件的按钮
var btnUpload = document.querySelector('#btnUpload')
// 2. 为按钮添加 click 事件监听
btnUpload.addEventListener('click', function() {
// 3. 获取到选择的文件列表
var files = document.querySelector('#file1').files
if (files.length <= 0) {
return alert('请选择要上传的文件!')
}
// ...后续业务逻辑
})
// 1. 创建 FormData 对象
var fd = new FormData()
// 2. 向 FormData 中追加文件
fd.append('avatar', files[0])
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数,指定请求类型与URL地址。其中,请求类型必须为 POST
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
// 3. 发起请求
xhr.send(fd)
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText)
if (data.status === 200) { // 上传文件成功
// 将服务器返回的图片地址,设置 为 标签的 src 属性
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else { // 上传文件失败
console.log(data.message)
}
}
}
/*
需求:单击按钮,上传文件给服务器
分析:
1)给按钮绑定点击事件
2)获取用户选择的文件
3)发送ajax请求,上传文件
*/
var uploadBtn = document.querySelector('#uploadBtn')
uploadBtn.addEventListener('click', function() {
// 获取到文件选择框
var file1 = document.querySelector('#file1')
// console.log(file1.files)
// 判断用户是否选择了文件
if (file1.files.length <= 0) {
return alert('请选择文件!')
}
// 获取用户选中的文件
file = file1.files[0]
// console.log(file)
// 使用FormData收集数据
var fd = new FormData()
fd.append('avatar', file)
// 发送ajax请求
var xhr = new XMLHttpRequest()
xhr.open('post', 'http://www.liulongbin.top:3006/api/upload/avatar')
xhr.send(fd)
xhr.onreadystatechange = function() {
// 判断请求是否成功
if (xhr.readyState === 4 && xhr.status === 200) {
console.log('请求成功了', xhr.responseText)
// 把服务器响应的json字符串转成对象
var data = JSON.parse(xhr.responseText)
console.log(data)
// data.url 图片在服务器的保存路径 /uploads/1645407308427_3d76ba7c13ad4ce295214ff040858c6b.jpg
// 给img标签设置src属性,展示图片
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
}
}
})
新版本的 XMLHttpRequest
对象中,可以通过监听 xhr.upload.onprogress
事件,来获取到文件的上传进度。语法格式如下:
e.lengthComputable 文件是否可计算大小
已上传的大小 / 总文件大小
// 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 监听 xhr.upload 的 onprogress 事件
xhr.upload.onprogress = function(e) {
// e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
if (e.lengthComputable) {
// e.loaded 已传输的字节
// e.total 需传输的总字节
var percentComplete = Math.ceil((e.loaded / e.total) * 100) + "%"
}
}
<link rel="stylesheet" href="./lib/bootstrap.css" />
<script src="./lib/jquery.js">script>
<div class="progress" style="width: 500px; margin: 10px 0;">
<div class="progress-bar progress-bar-info progress-barstriped active" id="percent" style="width: 0%">
0%
div>
div>
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
// 1. 计算出当前上传进度的百分比
var percentComplete = Math.ceil((e.loaded / e.total) * 100)
$('#percent')
// 2. 设置进度条的宽度
.attr('style', 'width:' + percentComplete + '%')
// 3. 显示当前的上传进度百分比
.html(percentComplete + '%')
// $("#percent").css("width", percentComplete);
// $("#percent").html(percentComplete);
}
}
xhr.upload.onload = function() {
$('#percent')
// 移除上传中的类样式
.removeClass()
// 添加上传完成的类样式
.addClass('progress-bar progress-bar-success')
}
<script src="./lib/jquery.js">script>
<input type="file" id="file1" />
<button id="btnUpload">上传button>
$('#btnUpload').on('click', function() {
// 1. 将 jQuery 对象转化为 DOM 对象,并获取选中的文件列表
var files = $('#file1')[0].files
// 2. 判断是否选择了文件
if (files.length <= 0) {
return alert('请选择图片后再上传!‘)
}
})
// 向 FormData 中追加文件
var fd = new FormData()
fd.append('avatar', files[0])
// fd.append('avatar',files)
$.ajax({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/upload/avatar',
data: fd,
// 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
contentType: false,
// 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
processData: false,
success: function(res) {
console.log(res)
if (res.status === 200) {
$("img").attr("src", "http://www.liulongbin.top:3006" + res.url);
}
}
})
Ajax
请求开始时,执行 ajaxStart
函数。可以在 ajaxStart
的 callback
中显示 loading
效果,示例代码如下:
// 自 jQuery 版本 1.8 起,该方法只能被附加到文档
$(document).ajaxStart(function() {
$('#loading').show()
})
注意: $(document).ajaxStart()
函数会监听当前文档内所有的 Ajax 请求。
Ajax
请求结束时,执行 ajaxStop
函数。可以在 ajaxStop
的 callback
中隐藏 loading
效果,示例代码如下:
// 自 jQuery 版本 1.8 起,该方法只能被附加到文档
$(document).ajaxStop(function() {
$('#loading').hide()
})
Axios
是专注于网络数据请求的库。
相比于原生的 XMLHttpRequest
对象,axios
简单易用。
相比于 jQuery
,axios
更加轻量化,只专注于网络数据请求。
axios
发起 get
请求的语法:
axios.get('url', { params: { /*参数*/ } }).then(callback)
具体的请求示例如下:
// 请求的 URL 地址
var url = 'http://www.liulongbin.top:3006/api/get'
// 请求的参数对象
var paramsObj = { name: 'zs', age: 20 }
// 调用 axios.get() 发起 GET 请求
axios.get(url, { params: paramsObj }).then(function(res) {
// res.data 是服务器返回的数据
var result = res.data
console.log(res)
})
// 发送get请求
$('#btn1').on('click', function() {
/*
axios.get('url地址', {params: 参数数据})
*/
axios.get('http://www.liulongbin.top:3006/api/getbooks', { params: { bookname: '三国演义' } }).then(function(res) {
// 请求成功之后的回调函数
// res 是axios封装的一个对象
// res.data 才是服务器响应回来的数据
console.log(res)
console.log(res.data)
})
})
axios
发起 post
请求的语法:
axios.post('url', { /*参数*/ }).then(callback)
具体的请求示例如下:
// 请求的 URL 地址
var url = 'http://www.liulongbin.top:3006/api/post'
// 要提交到服务器的数据
var dataObj = { location: '北京', address: '顺义' }
// 调用 axios.post() 发起 POST 请求
axios.post(url, dataObj).then(function(res) {
// res.data 是服务器返回的数据
var result = res.data
console.log(result)
})
// 发送post请求
$('#btn2').on('click', function() {
// axios.post('url', { /*参数*/ }).then(callback)
axios.post('http://www.liulongbin.top:3006/api/addbook', { bookname: '老李的一天', author: 'laoli', publisher: '黑马' }).then(function(res) {
console.log(res)
console.log(res.data)
})
})
axios
也提供了类似于 jQuery
中 $.ajax()
的函数,语法如下:
axios({
method: '请求类型',
url: '请求的URL地址',
data: { /* POST数据 */ },
params: { /* GET参数 */ }
}).then(callback)
发起get请求
document.querySelector('#btn3').addEventListener('click', function () {
var url = 'http://www.liulongbin.top:3006/api/get'
var paramsData = { name: '钢铁侠', age: 35 }
axios({
method: 'GET',
url: url,
params: paramsData
}).then(function (res) {
console.log(res.data)
})
})
发起post请求
document.querySelector('#btn4').addEventListener('click', function () {
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
name: '娃哈哈',
age: 18,
gender: '女'
}
}).then(function (res) {
console.log(res.data)
})
})
$('#btn3').on('click', function() {
// 发送get请求
axios({
method: 'get',
url: 'http://www.liulongbin.top:3006/api/getbooks',
params: { bookname: '三国演义' }
}).then(function(res) {
console.log(res)
console.log(res.data)
})
})
// ---------------------------------------------------------------
$('#btn4').on('click', function() {
// 发送post请求
axios({
method: 'post',
url: 'http://www.liulongbin.top:3006/api/addbook',
data: { bookname: '老李的两天', author: '老李', publisher: 'heima' }
}).then(function(res) {
console.log(res)=
console.log(res.data)
})
})
如果两个页面的协议,域名和端口都相同,则两个页面具有相同的源。
同源策略(英文全称 Same origin policy)是浏览器的一种安全机制 , 禁止向非同源的 url
发送 ajax
请求. (请求能发出去 , 但是会报错)
MDN
官方给定的概念:同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这
是一个用于隔离潜在恶意文件的重要安全机制
通俗的理解:浏览器规定,A 网站的 JavaScript,不允许和非同源的网站 C 之间,进行资源的交互,例如:
① 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
② 无法接触非同源网页的 DOM
③ 无法向非同源地址发送 Ajax 请求
跨域请求 : 向非同源的 url 发送跨域请求
出现跨域的根本原因:浏览器的同源策略不允许非同源的 URL 之间进行资源的交互
网页:http://www.test.com/index.html
接口:http://www.api.com/userlist
注意:浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!
现如今,实现跨域数据请求,最主要的两种解决方案,分别是 JSONP
和 CORS
。
**JSONP
:**出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET
请求,不支持 POST
请求。
**CORS
:**出现的较晚,它是 W3C
标准,属于跨域 Ajax
请求的根本解决方案。支持 GET
和 POST
请求。缺点是不兼容某些低版本的浏览器
由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。但是 标签不受浏览器同
源策略的影响,可以通过 src
属性,请求非同源的 js
脚本。
JSONP
的实现原理 : 动态创建一个
JSONP 缺点
由于 JSONP
是通过 标签的
src
属性,来实现跨域数据获取的,所以,JSONP
只支持 GET
数据请求,不支持 POST 请求。
实现步骤 :
<script>
function name(params) {
console.log("name");
console.log(params);
}
</script>
<script src="http://www.liulongbin.top:3006/api/jsonp?callback=name"></script>
单击按钮发送 jsonp 请求
<script>
function slf(data) {
console.log("slf");
console.log(data);
}
</script>
// 单击按钮发送 jsonp 请求
let btn = document.querySelector("#btn");
btn.addEventListener("click", function () {
// 1.创建script 标签
let script = document.createElement("script");
// 2.设置 src 属性
script.src = "http://www.liulongbin.top:3006/api/jsonp?callback=slf";
// 3.script 加载如页面
document.body.appendChild(script);
// onload 页面加载完事件
// 标签请求结束 删除script 标签
script.onload = function () {
document.body.removeChild(this);
};
});
使用 ajax 发送jsonp请求
$("#btn").on("click", function () {
$.ajax({
method: "get",
url: "http://www.liulongbin.top:3006/api/jsonp",
// 设置要发送的 jsonp请求
dataType: "jsonp",
// 自定义参数名称
// jsonp:"abc",
// 自定义函数名字
// jsonopCabblack:"二恶狗",
success: function (res) {
console.log(res);
},
});
});
jQuery
中JSONP
的实现过程jQuery
中的 JSONP
,也是通过 标签的
src
属性实现跨域数据访问的,只不过,jQuery
采用的是动态创建和移除标签的方式,来发起 JSONP
数据请求。
在发起 JSONP
请求的时候,动态向
中 append 一个 标签;
在 JSONP
请求成功以后,动态从
中移除刚才 append
进去的 标签;
防抖策略 当事件被触发是不会立即执行 , 延迟 n 秒后再执行回调 , 如果在这 n 秒内事件又被触发 , 则重新计算.
好处 :当频繁的触发某件事情时 , 我们能保证这个事件最终只能执行一次 , 能够减少一些不必要的回调执行 . 减少请求次数,节约请求资源;
用户在输入框中连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源;
JSONP
的请求keyup
事件时,立即清空 timer
,然后调用防抖的函数var timer = null // 1. 防抖动的 timer
function debounceSearch(keywords) { // 2. 定义防抖的函数
timer = setTimeout(function() {
// 发起 JSONP 请求
getSuggestList(keywords)
}, 500)
}
$('#ipt').on('keyup', function() { // 3. 在触发 keyup 事件时,立即清空 timer
clearTimeout(timer)
// ...省略其他代码
debounceSearch(keywords)
})
// 缓存对象
var cacheObj = {}
// 渲染建议列表
function renderSuggestList(res) {
// ...省略其他代码
// 将搜索的结果,添加到缓存对象中
var k = $('#ipt').val().trim()
cacheObj[k] = res
}
// 监听文本框的 keyup 事件
$('#ipt').on('keyup', function() {
// ...省略其他代码
// 优先从缓存中获取搜索建议
if (cacheObj[keywords]) {
return renderSuggestList(cacheObj[keywords])
}
// 获取搜索建议列表
debounceSearch(keywords)
})
节流策略(throttle
),可以减少一段时间内事件的触发频率。防止事件无限制触发 . 间隔时间内再去触发不会有任何效果
① 鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
② 懒加载时要监听计算滚动条的位置,但不必每次滑动都触发,可以降低计算的频率,而不必去浪费 CPU 资源;
不使用节流时实现鼠标跟随效果
$(function() {
// 获取图片元素
var angel = $('#angel')
// 监听文档的 mousemove 事件
$(document).on('mousemove', function(e) {
// 设置图片的位置
$(angel).css('left', e.pageX + 'px').css('top', e.pageY + 'px')
})
})
节流阀为空,表示可以执行下次操作;不为空,表示不能执行下次操作。
当前操作执行完,必须将节流阀重置为空,表示可以执行下次操作了。
每次执行操作前,必须先判断节流阀是否为空。
$(function() {
var angel = $('#angel')
var timer = null // 1.预定义一个 timer 节流阀
$(document).on('mousemove', function(e) {
if (timer) { return } // 3.判断节流阀是否为空,如果不为空,则证明距离上次执行间隔不足16毫秒
timer = setTimeout(function() {
$(angel).css('left', e.pageX + 'px').css('top', e.pageY + 'px')
timer = null // 2.当设置了鼠标跟随效果后,清空 timer 节流阀,方便下次开启延时器
}, 16)
})
})
防抖:如果事件被频繁触发,防抖能保证只有最后一次触发生效!前面 N 多次的触发都会被忽略!
节流:如果事件被频繁触发,节流能够减少事件触发的频率,因此,节流是有选择性地执行一部分事件!
是指通信的双方完成通信所必须遵守的规则和约定。
通俗的理解:通信双方采用约定好的格式来发送和接收消息,这种事先约定好的通信格式,就叫做通信协议。
客户端与服务器之间要实现网页内容的传输,则通信的双方必须遵守网页内容的传输协议。
网页内容又叫做超文本,因此网页内容的传输协议又叫做超文本传输协议(HyperText Transfer Protocol) ,简称 HTTP 协议。
HTTP 协议即超文本传送协议 (HyperText Transfer Protocol
) ,它规定了客户端与服务器之间进行网页内容传输时,所必须遵守的传输格式。
例如:
HTTP 协议采用了 请求/响应 的交互模型。
由于 HTTP
协议属于客户端浏览器和服务器之间的通信协议。因此,客户端发起的请求叫做 HTTP 请求,客户端发送到服务器的消息,叫做 HTTP 请求消息。
注意:HTTP
请求消息又叫做 HTTP
请求报文
客户端与服务器通信的过程是基于请求与响应的。其中:
HTTP
请求消息由请求行(request line
)、请求头部( header
) 、空行 和 请求体 4 个部分组成。
注意 :
在浏览器中,GET 请求比较特殊,它只有请求头,没有请求体。
在浏览器中,POST、PUT、PATCH、DELETE 请求既有请求头,又有请求体。
请求行由请求方式、URL 和 HTTP 协议版本 3 个部分组成,他们之间使用空格隔开。
请求头部用来描述客户端的基本信息,从而把客户端相关的信息告知服务器。比如:User-Agent 用来说明当前是什么类型的浏览器;
比如:User-Agent
用来说明当前是什么类型的浏览器;Content-Type
用来描述发送到服务器的数据格式;Accept
用来描述客户端能够接收什么类型的返回内容;Accept-Language
用来描述客户端期望接收哪种人类语言的文本内容。
请求头部由多行 键/值对 组成,每行的键和值之间用英文的冒号分隔
请求头部 – 常见的请求头字段
关于更多请求头字段的描述,可以查看 MDN
官方文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
最后一个请求头字段的后面是一个空行,通知服务器请求头部至此结束。
请求消息中的空行,用来分隔请求头部与请求体
请求体中存放的,是要通过 POST
方式提交到服务器的数据。
注意:只有 POST
请求才有请求体,GET
请求没有请求体!
响应消息就是服务器响应给客户端的消息内容,也叫作响应报文。
HTTP响应消息由状态行、响应头部、空行 和 响应体 4 个部分组成
状态行由 HTTP 协议版本、状态码和状态码的描述文本 3 个部分组成,他们之间使用空格隔开
响应头部用来描述服务器的基本信息。响应头部由多行 键/值对 组成,每行的键和值之间用英文的冒号分隔。
响应头部 – 常见的响应头字段
关于更多响应头字段的描述,可以查看 MDN
官方文档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers
在最后一个响应头部字段结束之后,会紧跟一个空行,用来通知客户端响应头部至此结束。
响应消息中的空行,用来分隔响应头部与响应体。
响应体中存放的,是服务器响应给客户端的资源内容。
HTTP 请求方法,属于 HTTP 协议中的一部分,请求方法的作用是:用来表明要对服务器上的资源执行的操作。最常用的请求方法是 GET
和 POST
。
概念:http 响应状态码(Status Code)由三个十进制数字组成,第一个十进制数字定义了状态码的类型,用来标识响应成功与否的状态。
作用:客户端浏览器根据响应状态码,即可判断出这次 http 请求是成功还是失败了。
HTTP 状态码共分为 5 种类型:
2** 范围的状态码,表示服务器已成功接收到请求并进行处理。常见的 2** 类型的状态码如下:
3** 范围的状态码,表示表示服务器要求客户端重定向,需要客户端进一步的操作以完成资源的请求。常见的 3** 类型的状态码如下:
4** 范围的状态码,表示客户端的请求有非法内容,从而导致这次请求失败。常见的 4** 类型的状态码如下:
5** 范围的状态码,表示服务器未能正常处理客户端的请求而出现意外错误。常见的 5** 类型的状态码如下
正确区分响应状态码和业务状态码的不同 , 从如下 3 个方面进行区分:
在响应头的状态行中所包含的状态码,叫做“响应状态码”
在响应体的数据中所包含的状态码,叫做“业务状态码”
响应状态码是由 http 协议规定的,具有通用性。每个不同的状态码都有其标准的含义,不能乱用。
业务状态码是后端程序员自定义的,不具有通用性。