ajax 学习第四天
ajax 学习第四天
文章目录
1. 同源策略
1.1 同源
- 定义:如果**两个页面的协议,域名和端口都相同**,则两个页面具有相同的源
- 图解
1.2 同源策略
-
浏览器提供的一个安全功能
-
概念:浏览器规定,A网站的JavaScript,不允许与非同源的网站C之间,进行资源的交互
- 无法读取非同源网页的Cookies、localStorage、IndexedDB
- 无法接触非同源网页的DOM
- 无法向非同源地址发起Ajax请求
2. 跨域
- 同源的反义词
- 浏览器的同源策略导致的
2.1 跨域拦截
2.2 实现跨域数据请求
- 两种解决方案
- JSONP
- CORS
- JSONP:兼容性好(兼容低版本IE),只支持GET请求,不支持POST请求
- CORS:W3C标准,属于跨域Ajax请求的根本解决方案,支持GET和POST请求,不兼容低版本IE
3. JSONP
- JSONP(JSON with Padding)是JSON的一种使用模式,可用于解决主流浏览器的跨域数据访问的问题
3.1 JSONP 实现的原理
-
原理:由于浏览器同源策略的限制,网页中无法提供Ajax请求
非同源的接口数据,但是
<script>
标签不受浏览器的影响,可以通过src属性,请求非同源的js脚本 -
同源策略的限制
<!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>Document</title>
<script src="./lib/jquery.js"></script>
</head>
<body>
<script>
$.ajax({
method: "get",
url: 'http://www.liulongbin.top:3006/api/jsonp',
data: {
name: "k",
age: 18
},
succsee: function(res) {
console.log(res);
}
})
</script>
</body>
</html>
- 效果图
3.2 JSONP 原理剖析
- 在本地script标签定义一个回调函数
- 通过另一个script标签的src属性让服务器去执行这个函数
<!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>Document</title>
</head>
<body>
<!-- 在一个script标签中定义一个函数 -->
<script>
function success(data) {
console.log("返回数据是:");
console.log(data);
}
</script>
<!-- 在另一个script标签中调用上面script标签的函数 -->
<script src="./js/test.js"></script>
</body>
</html>
- 本地js文件
// 调用success函数
success({ name: "k", age: 18 });
- 效果图
当src属性为服务器的接口时
<!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>Document</title>
</head>
<body>
<!-- 在一个script标签中定义一个函数 -->
<script>
function success(data) {
console.log("返回数据是:");
console.log(data);
}
</script>
<!-- 让服务器调用上述的函数-->
<script src="http://www.liulongbin.top:3006/api/jsonp?callback=success&name=k&age=30">
</script>
</body>
</html>
- 效果图
3.3 JSONP的缺点
- 原理是通过script标签的src属性,来实现跨域数据获取的,本质是js脚本请求,只能是get请求
- JSONP 与ajax没有任何关系,ajax使用了xhr对象,而JSONP是js脚本请求
3.4 jQuery中的JSONP
- jQuery中使用ajax函数发起jsonp请求
- 设置dataType:'jsonp’
<!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>Document</title>
<script src="./lib/jquery.js"></script>
</head>
<body>
<script>
$(function() {
$.ajax({
url: "http://www.liulongbin.top:3006/api/jsonp?name=k&age=30",
// 发起JSONP请求
dataType: 'jsonp',
success: function(res) {
console.log(res);
}
})
})
</script>
</body>
</html>
- 效果图
注意点
- url地址中会自动携带一个callback=jqueryxxx的参数,jQuery是随机生成的一个回调函数名称
自定义jQuery中JSONP的参数已经回调函数的名称
<!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>Document</title>
<script src="./lib/jquery.js"></script>
</head>
<body>
<script>
$(function() {
$.ajax({
url: 'http://www.liulongbin.top:3006/api/jsonp?name=k&age=30',
dataType: 'jsonp',
// 自定义jsonp参数和回调函数的名称
jsonp: 'callback',
jsonpCallback: 'abc',
success: function(res) {
console.log(res);
}
})
})
</script>
</body>
</html>
- 效果图
3.5 jQuery中JSONP的实现过程
- 动态的创建和移除script标签来实现
- 发起JSONP请求是,在head标签中创建一个script标签
- JSONP请求完成时,移除head标签中的script标签
<!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>Document</title>
<script src="./lib/jquery.js"></script>
</head>
<body>
<button id="btn">发起JSONP请求</button>
<script>
$(function() {
$("#btn").on("click", function() {
$.ajax({
url: 'http://www.liulongbin.top:3006/api/jsonp?name=k&age=30',
dataType: 'jsonp',
// 自定义jsonp参数和回调函数的名称
jsonp: 'callback',
jsonpCallback: 'abc',
success: function(res) {
console.log(res);
}
})
})
})
</script>
</body>
</html>
- 效果图
4. 防抖
-
当事件被触发后,延迟n秒后在执行回调函数,如果在这n秒内事件又被触发,则重新计时
-
原理:setTimeout()定时器的应用
-
图解
4.1 输入框的防抖
- 当用户输入完内容后,才进行建议词的提示,最终只发起了一次JSONP请求
示例:1个淘宝搜索案例
-
实现根据用户输入的部分内容给出提示词
-
**实现消抖:**再用户输入完毕后才发起请求获取搜索提示信息
-
实现结果缓存,用户的搜索结果再本地存储起来,当用户搜索同一关键字时,不需要再向服务器发起请求,而是本地获取
-
css部分
.container {
display: flex;
flex-direction: column;
align-items: center;
font-size: 12px;
}
.logo {
width: 225px;
height: 65px;
margin: 50px 0;
}
.tabs {
display: flex;
}
.tabs>div {
width: 55px;
height: 23px;
line-height: 23px;
text-align: center;
cursor: pointer;
}
.tabs>div:hover {
text-decoration: underline;
color: #ff5700;
}
.tab-active {
background-color: #ff5700;
font-weight: bold;
color: white;
}
.tabs>.tab-active:hover {
color: white;
text-decoration: none;
}
.search-box {
display: flex;
align-items: center;
}
.search-box .ipt {
box-sizing: border-box;
width: 500px;
height: 34px;
line-height: 30px;
margin: 0;
padding: 0;
padding-left: 5px;
outline: none;
border: 2px solid #ff5700;
}
.btnSearch {
margin: 0;
height: 34px;
border: none;
background-color: #ff5700;
color: white;
letter-spacing: 1em;
text-align: center;
width: 90px;
padding-bottom: 5px;
outline: none;
cursor: pointer;
}
.btnSearch:hover {
opacity: 0.9;
}
.tips .tips-item {
height: 25px;
/* background-color: pink; */
line-height: 22px;
font-size: 14px;
padding-left: 2px;
padding-top: 2px;
box-sizing: border-box;
margin-top: 5px;
cursor: pointer;
}
.tips .tips-item:hover {
background-color: rgb(221, 221, 221);
}
- 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" />
<title>Document</title>
<!-- 导入页面的基本样式 -->
<link rel="stylesheet" href="./css/search.css" />
<!-- 导入 jQuery -->
<script src="./lib/jquery.js"></script>
<script src="./lib/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 type="text" class="ipt" placeholder="请输入要搜索的内容" /><button class="btnSearch">
搜索
</button>
</div>
<!-- 搜索建议的ui结构 -->
<div class="tips">
</div>
</div>
</div>
<!-- 定义一个渲染的模板 -->
<script type="text/html" id="tep-getTips">
{{each result}}
<div class="tips-item">{{$value[0]}}</div>
{{/each}}
</script>
<script>
$(function() {
// 定义一个定时器
var timer = null;
// 定义一个缓存对象,存储服务器之前的搜索结果
var cache = {};
// 当搜索框中输入内容时,监听keyup事件
// 事件多次触发,先消抖
$(".ipt").on("keyup", function() {
// 消除定时器
clearTimeout(timer);
var text = $(this).val().trim();
if (text.length > 0) {
// 先判断cache中是否存在该搜索记录
if (cache[text]) {
var htmlstr = template('tep-getTips', cache[text]);
$(".tips").html(htmlstr).show();
return false;
}
// 发起内容匹配
// getTips(text);
// 延迟发起JSONP请求
debounceSearch(text);
} else {
// 输入为空,隐藏建议列表
return $(".tips").html("").hide();
}
})
// 创建一个获取提示词的函数
function getTips(text) {
$.ajax({
// 这个接口用于获取提示词
url: "https://suggest.taobao.com/sug?q=" + text,
// 发起跨域请求
dataType: "jsonp",
success: function(res) {
console.log(res);
// console.log(typeof res);
// 渲染ui页面,使用模板引擎
if (res.result.length < 0) {
//没有建议的数据
return $(".tips").html("").hide();
}
var htmlstr = template('tep-getTips', res);
$(".tips").html(htmlstr).show();
// 将数据存储到cache中,搜索记录作为键,结果作为值
cache[$(".ipt").val().trim()] = res;
}
})
}
// 创建一个防抖函数,让用户输入完毕后再发起跨域请求
function debounceSearch(text) {
// 开启定时器
timer = setTimeout(function() {
// 发起getTips请求
getTips(text);
}, 500)
}
})
</script>
</body>
</html>
- 效果图
5.节流
- 某事件在一段时间内被多次触发,当结果只执行一次
- 实现原理:定时器
一个案例
<!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>Document</title>
<script src="./lib/jquery.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
img {
position: absolute;
}
</style>
</head>
<body>
<!-- 天使图片,跟随鼠标移动 -->
<img src="./angel.gif" alt="">
<script>
$(function() {
var timer = null;
$(document).on("mousemove", function(e) {
if (timer) {
return;
}
timer = setTimeout(function() {
// 通过节流来控制计算的频率
$("img").css({
left: e.pageX,
top: e.pageY
})
console.log('ok');
timer = null;
}, 16)
})
})
</script>
</body>
</html>
- 效果图