JSONP跨域原理详解与百度联想词功能实现

作者:资源驿站时间:2026-10-22 17:26:45浏览:213

本文深入解析JSONP跨域原理,解释如何利用script标签绕过同源策略。通过动态创建script节点并回调函数处理数据,实现与后端接口的交互。最后结合百度搜索API,演示如何动态生成联想词列表,完成类似百度首页的搜索建议功能。

跨域问题与JSONP概述

跨域是指浏览器在执行脚本时,因安全限制而禁止访问不同源(协议、域名或端口任一不同)的资源。

通常情况下,Ajax请求受限于同源策略,必须在同一域名下才能发起异步请求。若尝试请求非白名单内的外部接口(如腾讯API),服务器会拒绝返回数据。由于向每个网站申请白名单并不现实,跨域技术应运而生。早期的iframe方案因无法直接操作内部DOM而实用性较低,目前JSONP是较为流行的跨域解决方案之一。

JSONP的全称是JSON with Padding。

从本质上看,JSONP依赖于HTML中的script标签。script、link和img等标签属于资源加载标签,它们不受同源策略限制,可以加载外部资源。因此,理解JSONP的关键在于理解script标签的跨域加载能力。

JSONP原理与script标签机制

script标签如何获取并执行数据?

操作系统识别文件类型主要依据文件内容而非后缀名,后缀名仅便于用户和软件查看。例如,将txt文件重命名为png后,图片查看器仍可能尝试解析其内容。同理,若将js文件后缀改为其他格式,浏览器在引入时仍可能执行其中的代码。这解决了script标签引入非js文件(如json或php)的技术可行性问题。

即使能引入资源,如何有效使用这些数据?

假设在a.json文件中定义了如下变量:


"text";

在HTML中加载该文件并执行,代码如下:


<script src="./a.json"></script>
<script>
alert(str); //text
</script>

上述代码可以正确执行。然而,标准JSON数据格式中并不包含变量或方法定义,这类似于以下写法:


var str="text";

在HTML中加载并执行上述代码,结果如下:


<script src="./a.json"></script>
<script>
alert(str); //error
</script>

这将导致报错。因此,跨域解决后,核心问题转化为如何安全地使用加载的资源。

回调函数与数据交互实现

解决方案是与后端约定一个回调函数,将数据作为参数传递给该函数。该函数需在前端预先定义,格式如下:


function solve(data){
//使用数据
}
<script src="./a.json"></script>

此时,a.json文件的内容定义如下:


solve(100);
solve({});
//相当于a.json里面的数据作为参数传递到了solve函数里面,然后,在solve函数里面操作这个数据就可以了

资源文件中需包含函数调用逻辑。

以引入PHP动态资源为例:


<?php
$t = isset($_GET['t']) ? $_GET['t'] : 'num';
$a = "111";
$b = "aaa";
if ($t == 'num') {
$data = json_encode($a);
} else {
$data = json_encode($b);
}
echo solve($data)

假设有两个按钮,分别请求数据$a和数据$b。若在PHP文件中为每种请求定义独立方法(如solve()),当请求类型多达n种时,需定义n个方法,显然不可行。更好的做法是在请求参数中指定回调函数名,例如:


<?php
$t = isset($_GET['t']) ? $_GET['t'] : 'num';
$callback = isset($_GET['callback']) ? $_GET['callback'] : 'fn1';

$arr1 = array('111111','22222222','33333333','4444444','555555555555555555555');
$arr2 = array('aaaaaaaaaaaa','bbbbbbbb','cccccccccccc','ddddddddd','eeeeeeeeeeee');

if ($t == 'num') {
$data = json_encode($arr1);
} else {
$data = json_encode($arr2);
}

echo $callback.'('.$data.');';

这种方式能有效规避多请求类型的处理难题。

若已理解上述原理,即掌握了跨域的概念及JSONP的解决思路。接下来通过百度搜索API进行实战练习。

此外,JSONP的加载应当是动态的,需通过代码动态创建script元素。

百度联想词功能实战

利用JSONP跨域实现百度首页联想词功能。

核心思路是利用jsonp的跨域特性,调用百度后台接口。根据input框内的输入内容,向后台获取数据,并将结果展示在搜索框下方。同时,li元素使用a标签包裹,基本实现了百度首页联想词收缩及点击跳转的功能。

运行效果截图如下。


  <script>
   var timer = null // 防抖动
   var domInput = document.getElementById('input')
   var domul = document.getElementsByTagName('ul')[0]
   domInput.oninput = function (e) {
    clearTimeout(timer) //防抖动
    timer = setTimeout(function () {
     var domScript = document.createElement('script')
     domScript.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+ e.target.value +'&cb=jsonpCb' // jsonp实现
     document.body.appendChild(domScript)
    }, 100)
   }
   function jsonpCb (data) { // jsonp的回调函数的实现
    let result = ''
    data.s.forEach(element => {
     result += '<li><a href= ' + 'https://www.baidu.com/s?wd=' + element + '>' + element +'</a></li>'
    });
    domul.innerHTML = result
   }
  </script> 

跨域问题与JSONP概述

支持点击联想词进行跳转。

跨域问题与JSONP概述

以上内容为本文的全部讲解,希望能对读者的学习有所帮助,欢迎继续支持本站。

作者最新文章