首先我们知道在HTML中img和script标签中的链接是可以访问到的,不会收到浏览器的跨域拦截。jsonp请求就是利用这个原理。
jsonp请求会在请求路径最后添加callback=func,服务器收到请求,将数据放到函数参数的位置例如func({code:0}),这个字符串返回,然后前端收到数据立刻执行函数
看代码
<body>
<input type="text" placeholder="请输入查询">
</body>
<script>
const input = document.querySelector('input');
input.addEventListener('input', handleChange);
function handleChange(event) {
//console.log(event.target.value)
jsonp("https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=33799,33823,31660,33848,33760,33855,33607,26350&wd="
+event.target.value+"&req=2&csor=1",'getData')
}
function jsonp(url,callback) {
let temp = document.createElement('script')
temp.src = url+'&cb='+callback
document.body.appendChild(temp)
}
function getData(response) {
console.log("服务器返回的数据",response)
}
</script>
上面例子用的百度搜索的API,最后的回调函数的的参数为cb,我们设置参数值为指定的函数名字符串即可。
用户输出后,监听函数执行,调用jsonp,函数生成一个script标签,给它添加src,src最后设置cb=getData,最后注入页面(这一步很关键),当数据请求完成就会调用callback。
增加显示和移除增加的script
<body>
<input type="text" placeholder="请输入查询">
<ul id='slist'></ul>
</body>
<script>
const input = document.querySelector('input');
input.addEventListener('input', handleChange);
function handleChange(event) {
//console.log(event.target.value)
jsonp("https://www.baidu.com/sugrec?pre=1&p=3&ie=utf-8&json=1&prod=pc&from=pc_web&sugsid=33799,33823,31660,33848,33760,33855,33607,26350&wd=" + event.target.value + "&req=2&csor=1", 'getData')
}
function jsonp(url, callback) {
let temp = document.createElement('script')
temp.src = url + '&cb=' + callback
document.body.appendChild(temp)
//移除,但请求已经发送了
document.body.removeChild(temp)
}
function getData(response) {
console.log("服务器返回的数据", response)
//显示数据
let fragment = document.createElement('ul')
if (!response.g) {
return
}
let len = response.g.length
for (let i = 0; i < len; i++) {
let li = document.createElement('li')
li.innerText = response.g[i].q
fragment.appendChild(li)
}
const item = document.querySelector('#slist')
while (item.firstChild) {
item.removeChild(item.firstChild)
}
document.getElementById('slist').appendChild(fragment)
}
</script>