同源策略(浏览器的一种机制)
概述:为了确保浏览器的安全而产生的一种同源策略,为了防止一些恶意的请求和保护对应 的隐私
同源策略对应的三个问题
同协议(http/https)
同ip地址(127.0.0.1本机)
同端口号(80HTTP 443HTTPS)
如果不同源就会产生跨域问题
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标签不受跨域影响的特性来解决跨域问题。(核心就是对应的请求是服务器通过回调函数传过来的而不需要主动请求)
代码实现
<!-- 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,param,day23JSONP,key,document From: https://www.cnblogs.com/zmfhtml5/p/16848882.html