1、使用jsonp实现跨域请求
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
jsonp跨域示例
- 实现功能:使用jsonp方法,在
php.pro
域名的demo1.html
中输入用户id,跨域请求php.io/jsonp.php
回调用户信息。
- 数据表:
php.pro
:demo1.html
# demo1.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>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #555;
}
body {
margin-top: 30px;
}
p {
width: 80%;
margin: 0 auto;
}
table {
width: 80%;
border: 1px solid;
border-collapse: collapse;
text-align: center;
margin: 0 auto;
}
table caption {
font-size: 1.2rem;
margin: 10px;
}
table td,
table th {
border: 1px solid;
padding: 5px;
}
</style>
</head>
<body>
<p>
<input type="text" name="userid" id="userid" placeholder="请输入ID" />
<button>跨域请求-JSONP</button>
</p>
<table>
<caption>
跨域请求结果:
</caption>
<thead>
<tr>
<td>id</td>
<td>name</td>
<td>email</td>
</tr>
</thead>
<tbody id="user"></tbody>
</table>
<script>
// 获取用户输入ID
var id = document.getElementById("userid");
// 获取提交按钮
var btn = document.querySelector("button");
// 监听事件
btn.addEventListener("click", function () {
// 动态生成script标签,发起jsonp请求
var script = document.createElement("script");
// url中的最后一个键值对,必须是一个回调
script.src =
"http://php.io/jsonp.php?id=" + id.value + "&action=getjsonp";
// 将script便签放到head里
document.head.appendChild(script);
});
function getjsonp(data) {
var obj = JSON.parse(data);
var table = document.createElement("tr");
if(obj.error!=="null"){
table.innerHTML += "<td>" + obj.id + "</td>";
table.innerHTML += "<td>" + obj.username + "</td>";
table.innerHTML += "<td>" + obj.email + "</td>";
document.querySelector("#user").appendChild(table);
}else{
table.innerHTML += "<td colspan='3'>未找到数据</td>";
document.querySelector("#user").appendChild(table);
}
}
</script>
</body>
</html>
php.io/jsonp.php
# jsonp.php
// 防止出现乱码
header('content-type:text/html;charset=utf-8');
// id: 查询参数,这是可选
$id = $_GET['id'];
// 前端的回调函数的名称[必选]
$callback = $_GET['action'];
$id = trim($_GET['id']);
$db = new PDO('mysql:host=localhost;dbname=php_pro', 'root', 'root');
$sql="SELECT `id`,`username`,`email` FROM `users` WHERE `id`='{$id}'";
$user = $db->query($sql)->fetch(PDO::FETCH_ASSOC);
if(!empty( $user)){
// 返回前端给回调的参数是一个json格式的数据
// 生成js函数的调用语句
echo $callback .' (\'' .json_encode($user) . '\')';
}else{
echo $callback .' (\'{"error":"null"}\')';
}
2、事件代理示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件代理简单示例</title>
<style>
ul li {
display: inline-block;
margin:10px;
}
ul li:hover{
background: #ccc;
cursor: pointer;
}
div {
width: 300px;
height: 150px;
background: #fff;
position: absolute;
top: 60px;
left: 50px;
border: 1px solid #ccc;
padding: 20px;
}
</style>
</head>
<body>
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
<li>item4</li>
<li>item5</li>
</ul>
<div></div>
<script>
// 事件代理(事件委托):就是将子元素的事件,绑定在父级上执行。
// 事件代理的好处:提高效率,不用循环为每个子元素绑定事件。
var navs = document.querySelector("ul");
navs.addEventListener("click", function (ev) {
// alert("绑定:"+ev.currentTarget.nodeName +"\r\n触发:"+ev.target.nodeName);
var div = document.querySelector("div");
if(ev.target.nodeName==="LI") {
div.innerHTML = "这是" + ev.target.innerHTML + "的内容";
}
});
</script>
</body>
</html>
总结
jsonp跨域请求:
- ① 前端定义一个函数,用来接收后台数据并渲染页面;比如:getjsonp(data)
- ② 使用script的src属性以键值对方式将函数名传递给后台(便于后台拼接函数名)
- ③ PHP后台接收到函数名, 将函数名拼接成函数表达式,函数参数使用json字符串;如 echo getjsonp({“id”:”111”,”name”:”peter”}
- ④ 前台收到后台返回数据是一个函数表达式,就直接执行了;
jsonp跨域请求:相当于使用script引入PHP文件,在后台输出一个函数表达式欺骗浏览器以达到跨域的目的。
本来作业是要求获取商品信息的,但没有商品数据,使用用户数据模拟了。
事件代理:
- 事件代理(事件委托):就是将子元素的事件,绑定在父级上执行。
- 事件代理的好处:提高效率,不用循环为每个子元素绑定事件。