Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:作业很有创意
此案例将使用JSONP的方式来请求跨域资源,并将其渲染到页面上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>跨域资源请求--JSONP</title>
<style>
table {
border-collapse: collapse;
border: 1px solid black;
}
td {
border: 1px solid black;
padding: 5px 10px;
background-color: lightsalmon;
}
</style>
</head>
<body>
<button>获取商品一的信息</button>
<button>获取商品二的信息</button>
<button>获取商品三的信息</button>
<button>获取商品四的信息</button>
<button>获取商品五的信息</button>
<h3></h3>
<table></table>
<script>
// 获取标题,表格,所有的按钮
let h3 = document.querySelector("h3");
let table = document.querySelector("table");
let btns = document.querySelectorAll("button");
// 循环给按钮绑定单击事件,创建script标签,以JSONP的方式请求跨域资源
for (let i = 0; i < btns.length; i++) {
btns.item(i).addEventListener(
"click",
function () {
let script = document.createElement("script");
script.src =
"http://front.test/demo.php?id=" + (i + 1) + "&jsonp=handle";
document.head.appendChild(script);
},
false
);
}
// 脚本标签中src属性的回调函数参数,这个data是服务器端返回的json格式字符串
function handle(data) {
// console.log(data);
let obj = JSON.parse(data);
// console.log(obj);
h3.innerHTML = obj.title;
let tr = document.createElement("tr");
tr.innerHTML += "<td>" + obj.data.list + "</td>";
tr.innerHTML += "<td>" + obj.data.name + "</td>";
tr.innerHTML += "<td>" + obj.data.message + "</td>";
tr.innerHTML += "<td>" + obj.data.spec + "</td>";
tr.innerHTML += "<td>" + obj.data.price + "</td>";
table.appendChild(tr);
}
</script>
</body>
</html>
<?php
header('content-type:text/html;charset=utf-8');
// 获取链接中的GET参数,对应id和一个回调函数
$id = $_GET['id'];
$callback = $_GET['jsonp'];
// 模拟接口数据,这个数据是一个数组,但是数组元素一定是json样式,但并不是json
$datas = [
0 => '{"list":"商品一","name":"荣耀 Play4T Pro","message":"OLED屏幕指纹 4800万高感光夜拍三摄","spec":"全网通 8GB+128GB","price":"1598"}',
1 => '{"list":"商品二","name":"iphone 11","message":"双卡双待 数码变焦 人像模式","spec":"全网通 128GB","price":"5899"}',
2 => '{"list":"商品三","name":"Redmi 10X","message":"4800万超清四摄 小孔全面屏 大电量","spec":"全网通 4GB+128GB","price":"999"}',
3 => '{"list":"商品四","name":"华为 nova 7 SE","message":"麒麟820 5G Soc芯片 6400万高清四摄","spec":"全网通 8GB+128GB","price":"2399"}',
4 => '{"list":"商品五","name":"vivo iQOO Z1 ","message":"晓龙756G 120HZ竞速屏 超大电池 双模","spec":"全网通 6GB+128GB","price":"1798"}'
];
// 因为要根据GET传过来的id来获取对应的数据,所以判断此id在数据数组中是否存在,若存在,则取出对应的数据
if (array_key_exists(($id-1),$datas)){
$data = $datas[$id-1];
}
// 将取出来的数据以字符串拼接的方式拼成json样式
$json = '{"title":"商品信息表:","data":' . $data . '}';
// 以字符串拼接的方式生成一条回调函数语句,且将数据转为json,然后返回给前端
echo $callback.'('. json_encode($json) .')';
案例效果如下:
本次案例将修改上面的跨域请求实战案例,因为上面的案例是通过循环按钮,绑定事件的方式,这样很麻烦,而且执行效率也不高,所以通过改进,可以考虑将所有的按钮事件委托给另外一个标签来执行,利用事件冒泡的原理来实现自动绑定点击事件,并且通过dataset自定义属性,将id自动绑定到事件触发者身上,从而实现自动获取商品信息,此次只需要修改html里面的文件即可,修改如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>跨域资源请求--JSONP实战案例(使用事件代理)</title>
<style>
table {
border-collapse: collapse;
border: 1px solid black;
}
td {
border: 1px solid black;
padding: 5px 10px;
background-color: lightsalmon;
}
a {
padding: 5px 10px;
background-color: limegreen;
}
a:hover {
background-color: green;
color: white;
cursor: pointer;
}
</style>
</head>
<body>
<div>
<!-- 使用dataset自定义属性设置id,便于自动获取到JS脚本标签中的src -->
<a data-id="1">获取商品一的信息</a>
<a data-id="2">获取商品二的信息</a>
<a data-id="3">获取商品三的信息</a>
<a data-id="4">获取商品四的信息</a>
<a data-id="5">获取商品五的信息</a>
</div>
<h3></h3>
<table></table>
<script>
// 获取标题、表格、事件代理者div
let h3 = document.querySelector("h3");
let table = document.querySelector("table");
let div = document.querySelector("div");
// 给事件代理者添加事件监听
div.addEventListener(
"click",
function (ev) {
let script = document.createElement("script");
// console.log(ev.target.dataset.id);
// 通过dataset对象获取到商品id
script.src =
"http://front.test/demo.php?id=" +
ev.target.dataset.id +
"&jsonp=handle";
document.head.appendChild(script);
},
false
);
// 脚本标签中src属性的回调函数参数,这个data是服务器端返回的json格式字符串
function handle(data) {
// console.log(data);
let obj = JSON.parse(data);
// console.log(obj);
h3.innerHTML = obj.title;
let tr = document.createElement("tr");
tr.innerHTML += "<td>" + obj.data.list + "</td>";
tr.innerHTML += "<td>" + obj.data.name + "</td>";
tr.innerHTML += "<td>" + obj.data.message + "</td>";
tr.innerHTML += "<td>" + obj.data.spec + "</td>";
tr.innerHTML += "<td>" + obj.data.price + "</td>";
table.appendChild(tr);
}
</script>
</body>
</html>
最后效果是一样的,但是没有用循环,效率就会高些了: