JSONP
JSONP(JSON with Padding)是资料格式JSON的一种“使用模式”,可以让网页从别的网域要资料。
由于同源策略,一般来说位于server1.example.com的网页无法与不是 server1.example.com的伺服器沟通,而HTML
的 <script>
元素是一个例外。利用 <script>
元素的这个开放策略,网页可以得到从其他来源动态产生的JSON资料,而这种使用模式就是所谓的 JSONP。用JSONP抓到的资料并不是JSON,而是任意的JavaScript,用 JavaScript直译器执行而不是用JSON解析器解析。
index.html
<div class="container">
<ul class="news">
<li>习近平:坚持中国特色社会主义社会治理之路</li>
<li>在组织生活会上普通党员习近平说了啥 喜迎十九大</li>
<li>重访习近平十八大以来国内考察地 《辉煌中国》</li>
</ul>
<button id="btn">换一组</button>
</div>
<script>
$('#btn').addEventListener('click',function(){
// 为按钮添加点击事件
var script = document.createElement('script');
// 创建一个script标签
script.src='http://localhost:8080/getNews?callback=appendHtml'
// 为script标签设置地址
document.head.appendChild(script)
//在head里添加script标签
document.head.removeChild(script)
//移除head里的script标签
})
// 处理返回的数据appendHtml(["xxx","xxx","xxx"])
function appendHtml(news){
var html = ''
for(var i = 0;i<news.length;i++){
html += '<li>'+news[i]+'</li>'
// 把后台传递过来的数据,拆开加在<li></li>内
}
$('.news').innerHTML = html;
//把<ul class="news"></ul>中的内容替换为处理好的数据
}
function $(id){
return document.querySelector(id)
}
</script>
router.js
app.get('/getNews',function(req,res){
var news = [
"<strong>习近平:坚持中国特色社会主义社会治理之路</strong>",
"在组织生活会上普通党员习近平说了啥 喜迎十九大",
"重访习近平十八大以来国内考察地 《辉煌中国》",
"李克强同李显龙会谈 张德江主持会议 刘云山访越",
"大国网信安全护航 2017年国家网络安全宣传周",
"侠客岛:李显龙时隔近4年为何“突然”访华?",
"<strong>墨西哥地震致一学校教学楼倒塌 约百名学生失踪<stong>",
"深圳一小学65名学生现身体不适 官方:已停用操场",
"媒体:想知道中国海军有多强?仅需一个细节",
"特朗普演讲:朝鲜半岛无核化是唯一可接受的未来",
"外媒:中国高铁网络预示着“高流动性时代”的到来",
"外国专家:北斗已超越欧盟、俄罗斯卫星导航系统"
]
// 内容库
var data = []
for(var i = 0;i<3;i++){
var index = parseInt(Math.random()*news.length)
// parseInt取整,抽取内容库的随机数字
data.push(news[index])
// 把这条随机的新闻,传给data数组
news.splice(index,1)
//移除这条新闻,避免重复
}
var cb = req.query.callback;
// 获取传递的callback值
if(cb){
res.send(cb+'('+JSON.stringify(data)+')');
//JSON.stringify 将JavaScript的值转化为JSON
//如果有callback的值,返回callback值+(["xxx","xxx","xxx"])
}else{
res.send(data);
//如果没有,返回["xxx","xxx","xxx"]
}
})
CORS
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。 实现方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。
例:http://a.jrg.com:8080网站向http://b.jrg.com:8080/getNews获取数据
html
<div class="container">
<ul class="news">
<li>习近平:坚持中国特色社会主义社会治理之路</li>
<li>在组织生活会上普通党员习近平说了啥 喜迎十九大</li>
<li>重访习近平十八大以来国内考察地 《辉煌中国》</li>
</ul>
<button id="btn">换一组</button>
</div>
script
$('#btn').addEventListener('click',function(){
var xhr = new XMLHttpRequest();
xhr.open('get','http://b.jrg.com:8080/getNews',true)
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readyState===4 && xhr.status===200){
appendHtml( JSON.parse(xhr.responseText) )
}
}
})
function appendHtml(news){
var html = '';
for(var i = 0;i<news.length;i++){
html += '<li>'+news[i]+'</li>'
}
$('.news').innerHTML = html;
}
function $(id){
return document.querySelector(id);
}
router.js
app.get('/getNews',function(req,res){
var news = [
"<strong>习近平:坚持中国特色社会主义社会治理之路</strong>",
"在组织生活会上普通党员习近平说了啥 喜迎十九大",
"重访习近平十八大以来国内考察地 《辉煌中国》",
"李克强同李显龙会谈 张德江主持会议 刘云山访越",
"大国网信安全护航 2017年国家网络安全宣传周",
"侠客岛:李显龙时隔近4年为何“突然”访华?",
"<strong>墨西哥地震致一学校教学楼倒塌 约百名学生失踪<stong>",
"深圳一小学65名学生现身体不适 官方:已停用操场",
"媒体:想知道中国海军有多强?仅需一个细节",
"特朗普演讲:朝鲜半岛无核化是唯一可接受的未来",
"外媒:中国高铁网络预示着“高流动性时代”的到来",
"外国专家:北斗已超越欧盟、俄罗斯卫星导航系统"
]
var data = []
for(var i = 0;i<3;i++){
var index = parseInt(Math.random()*news.length)
data.push(news[index])
news.splice(index,1)
}
res.header("Access-Control-Allow-Origin","http://a.jrg.com:8080")
// 返回来自http://a.jrg.com:8080的数据请求
//res.header("Access-Control-Allow-Origin","*")
//返回所有网站的数据请求
res.send(data);
})
降域
a.html
<div class="ct">
<h1>降域</h1>
<div class="main">
<input type="text" placeholder="http://a.jrg.com:8080/a.html">
</div>
<iframe src="http://b.jrg.com:8080/b.html" frameborder="0"></iframe>
</div>
<script>
document.querySelector('.main input').addEventListener('input',function(){
//给当前窗口的input绑定一个输入事件
window.frames[0].document.querySelector('input').value = this.value;
//把当前输入input的值,赋给第一个frames的input的值
})
document.domain = "jrg.com"
//降域
</script>
b.html
<input id="input" type="text" placeholder="http://b.jrg.com:8080/b.html">
<script>
document.querySelector('#input').addEventListener('input',function(){
//获取页面上的input,添加输入事件
window.parent.document.querySelector('input').value = this.value;
//把当前frame的input的值,赋给父级页面的input的值
})
document.domain = "jrg.com"
//降域
</script>
postMessage
postMessage对于不同的域下,可以向他发送一个数据,如果对方接受认可这个数据,那就可以去使用,如果对象没有去监控这个数据,就没有任何作用。
a.html
<div class="ct">
<h1>postMessage</h1>
<div class="main">
<input type="text" placeholder="http://a.jrg.com:8080/a.html">
<iframe src="http://b.jrg.com:8080/b.html" frameborder="0"></iframe>
</div>
<script>
$('.main input').addEventListener('input',function(){
window.frames[0].postMessage(this.value,"*");
})
window.addEventListener('message',function(e){
$('.main input').value = e.data
})
function $(id){
return document.querySelector(id)
}
</script>
b.html
<input id="input" type="text" placeholder="http://b.jrg.com:8080/b.html">
<script>
$('#input').addEventListener('input',function(){
window.parent.postMessage(this.value,"*")
})
window.addEventListener('message',function(e){
$('#input').value = e.data
})
function $(id){
return document.querySelector(id)
}
</script>
其他跨域方式
用到的函数
- JSON.stringify()方法将一个 JavaScript 值转换为一个 JSON 字符串,如果指定了一个 replacer 函数,则可以替换值,或者如果指定了一个 replacer 数组,可选地仅包括指定的属性。
- parseInt() 函数可解析一个字符串,并返回一个整数。
- JSON.parse()方法用于将一个 JSON 字符串转换为对象。