问题:

页面中有一个按钮,点击之后会更新网页中的一个盒子的内容。

Ajax可以很容易的满足这种无须刷新整个页面就可以实现数据变换的需求。

但是,Ajax有一个缺点,就是他不允许跨域请求资源。

如果我的代码在codepen上,我不能将我的数据放到codepen网站上,那么我只能放到我自己的服务器中,这样的话,就无法通过Ajax访问到这个数据了。

解决:

想要实现这种跨域资源请求,有很多解决办法,列举出一部分:

  1. 让服务器来加载远程数据,然后在用户请求时提供给浏览器。
  2. 用<script>或是<iframe>标签加载外来文件。(因为他们的src属性允许获得任何地方的资源。)
  3. W3C制定的Cross-Origin Resource Sharing(CORS,跨域资源共享)。
  4. JSONP

JSONP的诞生及原理:

jsonp的原理其实和第二种解决方法一模一样,只不过他更加方便,然后这种跨域沟通的手段就被赋予了一个名字“JSONP”。

所以首先要弄懂第二种方式是怎么工作的:

原理:如果一个页面加载了一个外来的JS文件,浏览器就会自动执行这个文件中的代码。

所以假如localhost想要使用jsonhost上面的一个JSON数据,localhost就可以让jsonhost来帮他完成这件事情,jsonhost提供给他一个js文件,往要调用的函数中传入需要的数据,结果是和localhost自己调用函数的效果一模一样了。

jsonhost:

<script type="text/javascript">
   var json='["customername1","customername2"]';
   callbackFunction(json); 
</script>

localhost:

<script type="text/javascript">
   var json='["customername1","customername2"]';
   callbackFunction(json); 
</script>
<script type="text/javascript">
function callbackFunction(result)
{
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
</script>

这样,localhost就已经可以使用jsonhost中的数据了。

然后localhost说,我希望可以在我的用户点击一次按扭时,就执行一遍callbackFunction(json),而不是页面加载后执行一次。

于是他就需要动态的创建<script>标签:

function callbackFunction(result)
{
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
$(".btn").click(function(){
var script = document.createElement('script');
script.setAttribute('src', "http://jsonhost/json.js");
document.getElementsByTagName('header')[0].appendChild(script);
});

这样完成之后,效果就和用Ajax异步请求一样了。

到这里,故事仿佛就要这样结束了,但是突然有一天,另一个otherhost跑来和jsonhost说,他想要通过jsoncallbackFunction处理json,jsonhost就很为难,于是他们聚在一起,想要找到一个办法,可以不需要全部使用同一个函数名,也可以获取同一个数据。

最终他们想到了一个完美的办法——jsonhost用的函数名用一个变量代替,localhost和otherhost请求数据的时候,传入这个变量名,这样就可以各自决定各自使用的函数名了。

jsonhost:

<?php
header('Content-type: application/json'); //告诉接收数据的对象此页面输出的是json数据 $json = '["customername1","customername2"]'; echo $_GET['callback'] . "(" . $json . ")";
?>

localhost:

<script type="text/javascript">

    function getJson(url,funName){
var script = document.createElement('script');
script.setAttribute('src', url+funName);
document.getElementsByTagName('head')[0].appendChild(script);
}
function callbackFunction(result)
{
var html = '<ul>';
for(var i = 0; i < result.length; i++)
{
html += '<li>' + result[i] + '</li>';
}
html += '</ul>';
document.getElementById('divCustomers').innerHTML = html;
}
$(".btn").click(function(){
getJson("http://jsonhost/jsonp.php?jsoncallback=","callbackFunction");
}); </script>

otherhost:

<script type="text/javascript">

    function getJson(url,funName){
var script = document.createElement('script');
script.setAttribute('src', url+funName);
document.getElementsByTagName('head')[0].appendChild(script);
}
function jsoncallbackFunction(result)
{
console.log(result);
}
$(".btn").click(function(){
getJson("http://jsonhost/jsonp.php?jsoncallback=","jsoncallbackFunction");
}); </script>

这样一来,使用什么函数名都是不同host自己的事情,他们互不干扰,jsonhost也不用操心这件事,专心提供数据就可以了。其他host也纷纷前来获取json。于是这种模式被广泛使用,然后这种通信方式就被命名为“JSONP”。

如果用jQuery的话,就不用自己命名函数并传递给参数了,因为这个函数名一点也不重要,他只是个代号而已,jQuery会帮我们自动生成一个函数名,然后将得到的数据传给这个函数。jQuery还会帮我们创建script标签, 我们只要关心如何处理这个数据就好了。

<script src="http://apps.bdimg.com/libs/jquery/1.8.3/jquery.js"></script>
<script>
$.getJSON("http://jsonhost/jsonp.php?jsoncallback=?", function(data) {
var html = '<ul>';
for(var i = 0; i < data.length; i++)
{
html += '<li>' + data[i] + '</li>';
}
html += '</ul>'; $('#divCustomers').html(html);
});
</script>

jQuery把JSONP封装到Ajax里面,但本质上这两种技术是完全不同的。

JSONP的原理是,当前网页动态执行异域返回的js代码,这个代码是个执行请求数据的函数。浏览器执行这个函数,效果和当前域获得数据执行函数是一样的。

应用实例:

知道了原理之后,迫不及待的想要用一下JSONP来获取数据。这里用PHP来实现。

首先,需要有个服务器,如果没有服务器的话,可以使用wampserver软件模拟一个,这个软件还会建立一个集成环境,可以运行PHP文件。点击查看wampserver

有了自己的服务器和PHP运行环境之后,就可以开始了。想要在codepen上获取本地数据。

本机PHP:

<?php
header('Content-type: application/json'); //告诉接收数据的对象此页面输出的是json数据 $quotes = '[{
"quote": "If you can\'t get rid of the skeleton in your closet, you\'d best teach it to dance.",
"author": "George Bernard Shaw"
},
{
"quote": "We\'ll always have Paris.",
"author": "Casablanca"
},
{
"quote": "A mathematician is a device for turning coffee into theorems.",
"author": "Paul Erdos"
},
{
"quote": "Do, or do not. There is no \'try\'.",
"author": "Star Wars: Empire Strikes Back"
},
{
"quote": "Some cause happiness wherever they go; others, whenever they go.",
"author": "Oscar Wilde"
},
{
"quote": "Problems worthy of attack prove their worth by fighting back.",
"author": "Paul Erdos"
},
{
"quote": "Maybe this world is another planet\'s Hell.",
"author": "Aldous Huxley"
}]'; echo $_GET['callback'] . "(" . $quotes . ")";
?>

codepen上的js:

function update(){
var index=Math.floor(Math.random()*11);
$.getJSON("http://localhost/quotes.php?callback=?",function(data){
var num=Math.floor(Math.random()*6);
$(".wrap").fadeOut(600,function(){
$(".quo").html(data[num].quote);
$(".auth").html(data[num].author);
$("body, .quote-box button").css("background-color",colors[index]);
$(".wrap").css("color",colors[index]);
}).fadeIn(600);
});
} $(document).ready(function(){
update();
$(".update").click(update);
});

点击查看在线demo,必须将本机模拟成服务器并建立PHP环境并添加了PHP文件才能运行。

而且要注意把codepen的https改成http。

成功之后可以看到,发送的请求中,传给callback的是一个jQuery自动生成的函数:

返回的也是这个函数调用数据:

如果不想自己配置的话,可以应用其他网站提供的API,实现原理是一样的。demo

参考:

VUE -- JSONP的诞生、原理及应用实例的更多相关文章

  1. JSONP的诞生、原理及应用实例

    问题: 页面中有一个按钮,点击之后会更新网页中的一个盒子的内容. Ajax可以很容易的满足这种无须刷新整个页面就可以实现数据变换的需求. 但是,Ajax有一个缺点,就是他不允许跨域请求资源. 如果我的 ...

  2. 西安电话面试:谈谈Vue数据双向绑定原理,看看你的回答能打几分

    最近我参加了一次来自西安的电话面试(第二轮,技术面),是大厂还是小作坊我在这里按下不表,先来说说这次电面给我留下印象较深的几道面试题,这次先来谈谈Vue的数据双向绑定原理. 情景再现: 当我手机铃声响 ...

  3. vue深入响应式原理

    vue深入响应式原理 深入响应式原理 — Vue.jshttps://cn.vuejs.org/v2/guide/reactivity.html 注意:这里说的响应式不是bootsharp那种前端UI ...

  4. vue深入相应式原理

    Vue 最显著的特性之一便是不太引人注意的响应式系统(reactivity system).模型层(model)只是普通 JavaScript 对象,修改它则更新视图(view).这会让状态管理变得非 ...

  5. Vue 数据响应式原理

    Vue 数据响应式原理 Vue.js 的核心包括一套“响应式系统”.“响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码.例如,视图渲染中使用了数据,数据改变后,视图也会自动更新. 举个简单 ...

  6. vue的双向绑定原理解析(vue项目重构二)

    现在的前端框架 如果没有个数据的双向/单向绑定,都不好意思说是一个新的框架,至于为什么需要这个功能,从jq或者原生js开始做项目的前端工作者,应该是深有体会. 以下也是个人对vue的双向绑定原理的一些 ...

  7. 深入解析vue.js响应式原理与实现

    vue.js响应式原理解析与实现.angularjs是通过脏检查来实现数据监测以及页面更新渲染.之后,再接触了vue.js,当时也一度很好奇vue.js是如何监测数据更新并且重新渲染页面.vue.js ...

  8. Vue的响应式原理

    Vue的响应式原理 一.响应式的底层实现 1.Vue与MVVM Vue是一个 MVVM框架,其各层的对应关系如下 View层:在Vue中是绑定dom对象的HTML ViewModel层:在Vue中是实 ...

  9. 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?

    关注「松宝写代码」,精选好文,每日一题 ​时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...

随机推荐

  1. java 计算精度处理

    1.设计思想: 定义两个字符串number1和number2,分别输入一串数字,然后定义两个BigDecimal类的对象f1,f2分别接收number1和number2的值,然后调用BigDecima ...

  2. 【转】通过制作Flappy Bird了解Native 2D中的RigidBody2D和Collider

    作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 在第一篇文章[Unity3D基础教程] ...

  3. Centos安装后的一些必要处理工作

    1永久关闭selinux,修改成permissive或者disabled(建议),修改完需重启 2配置network 3.禁止ping(可选,一般不需要禁止)(默认为0位启用ICMP协议,1为禁止), ...

  4. 【转】PHP对象在内存中的分配

    对像在PHP 里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢?内存从逻辑上 说大体上是分为4 段,栈空间段.堆空 ...

  5. JZOJ 5305 C先生

    题意: 有一个n个点,m条边的图,没有重边.自环,且每一条边最多属于一个环路. 给出q组询问,每次询问u,v两点间的路径有多少种可能. 思路: 先看下方样例说明: 由样例说明可以得知,路径上每经过一个 ...

  6. gitHub优秀android项目

    转自:http://blog.csdn.net/shulianghan/article/details/18046021 主要介绍那些不错个性化的View,包括ListView.ActionBar.M ...

  7. MySQL5.7源码安装问题汇总

    编译安装mysql5.7版本,想试用一下新的版本特性,发现跟之前的5.6版本编译有了一些变化,总结一下避免以后继续入坑.5.6安装方式 cmake版本 5.7编译cmake要求版本最低为2.8,当前为 ...

  8. JAVA中GC时finalize()方法是不是一定会被执行?

    在回答上面问题之前,我们一定要了解JVM在进行垃圾回收时的机制,首先: 一.可达性算法  要知道对象什么时候死亡,我们需要先知道JVM的GC是如何判断对象是可以回收的.JAVA是通过可达性算法来来判断 ...

  9. LINK : fatal error LNK1104: 无法打开文件“mfc71.lib”(转)

    原文转自 http://blog.csdn.net/mxclxp/article/details/8196142 [环境]  Windows XP OS:  Visual Studio 2008:  ...

  10. git使用教程2-更新github上代码【转载】

    本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/git/ 前言 前面一篇已经实现首次上传代码到github了,迈出了装逼第一步,本篇继续 ...