同源策略(浏览器的一种机制)
概述:
浏览器为了安全,他产生一种同源策略,这个策略是为了防止一些恶意的请求,保护对应的隐私。
同源策略主要是对应三个内容 分别为
- 同协议 (http/https)
- 同ip地址 (127.0.0.1本机)
- 同端口号 (80 HTTP的 443 HTTPS的)
如果不同源就会产生一个问题就是跨域问题
import {ajax} from './ajax_promise.js'
//请求一个地址 https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
ajax('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn',{}).then(res=>{
console.log(res);
})
跨域问题的产生(以下任意一点不同就会跨域)
- 协议不一样
- 端口不一样
- ip地址不一样
- 以文件访问(不同的文件资源也会跨域)
跨域问题的解决
1.前端解决 (JSONP)(需要后端给的是JSONP的接口)
2.后端解决 (在对应的响应头进行设置)
respones.setHeader('Access-Control-Allow-Origin','*')//所有的地址都可以访问我
respones.setHeader('Access-Control-Allow-Origin-Method','*')//所有的请求都可以访问我
3.使用服务器代理(proxy)
4.使用websocket(走的不是http协议)
JSONP
概述:
他是通过script标签不受跨域的影响的特性来解决跨域问题的。(核心就是对应的请求不是我去请求而是服务器自己请求自己将数据通过回调函数传给我),他的核心还是一个get请求。
简单的JSONP
<!-- wd表示关键词 cb表示回调函数 -->
<script>
//他会自动执行你传入的回调函数并且将结果传递给这个函数
//res里面就会执行完的数据
function callback(res){
console.log(res);
}
</script>
<script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=callback"></script>
jsonp封装
//请求地址 参数 回调函数 回调函数
export const jsonp=(url,param,callbackName,callback)=>{
//提取param参数加入到url中
for(let key in param){
if(url.includes('?')){
url += `&${key}=${param[key]}`
}else{
url += `?${key}=${param[key]}`
}
}
//将回调函数加给window
//随机生成一个名字
let fnName = 'fn'+Date.now()+Math.ceil(Math.random()*30)
window[fnName] = callback
//将回调的函数及相关名字拼接到url
url += `&${callbackName}=${fnName}`
console.log(url);
//创建一个script标签
let script = document.createElement('script')
//给这个script标签设置src地址
script.src = url
document.body.appendChild(script)
//(必须等待script标签加入到页面才会触发)
script.onload = ()=>{
// 将script标签加入到对应的页面
// 将window的函数删了
delete window[fnName]
//再将script标签删除
script.remove()
}
}
案例:百度搜索
<input type="text" />
<ul>
</ul>
<script type="module">
// 导入jsonp
import {jsonp} from './JSONP.js'
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
document.querySelector('input').oninput = function(){
jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{
wd:this.value
},"cb",(res)=>{
document.querySelector('ul').innerHTML = ""
res.s.forEach(v=>{
document.querySelector('ul').innerHTML += `
<li>${v}</li>
`
})
})
}
</script>
JSONP的promise封装
//请求地址 参数 回调函数 回调函数
export const jsonp=(url,param,callbackName)=>{
return new Promise((resolve,reject)=>{
//提取param参数加入到url中
for(let key in param){
if(url.includes('?')){
url += `&${key}=${param[key]}`
}else{
url += `?${key}=${param[key]}`
}
}
//将回调函数加给window
//随机生成一个名字
let fnName = 'fn'+Date.now()+Math.ceil(Math.random()*30)
window[fnName] = resolve
//将回调的函数及相关名字拼接到url
url += `&${callbackName}=${fnName}`
console.log(url);
//创建一个script标签
let script = document.createElement('script')
//给这个script标签设置src地址
script.src = url
document.body.appendChild(script)
//(必须等待script标签加入到页面才会触发)
script.onload = ()=>{
// 将script标签加入到对应的页面
// 将window的函数删了
delete window[fnName]
//再将script标签删除
script.remove()
}
script.onerror =()=>{
reject()
}
})
}
测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
ul{
list-style: none;
}
</style>
</head>
<body>
<input type="text" />
<ul>
</ul>
<script type="module">
// 导入jsonp
import {jsonp} from './JSONP_promise.js'
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
document.querySelector('input').oninput = function(){
jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',{
wd:this.value
},"cb").then((res)=>{
document.querySelector('ul').innerHTML = ""
res.s.forEach(v=>{
document.querySelector('ul').innerHTML += `
<li>${v}</li>
`
})
})
}
</script>
</body>
</html>
标签:script,url,res,JSONP,param,day23,key,讲解,document
From: https://www.cnblogs.com/jje105/p/16849316.html