同源策略 ( 浏览器的一种机制 )
概述 :
同源策略主要有三个内容 , 分别为
-
同协议 ( http / https )
-
同ip地址 ( 127.0.0.1 表示本机 )
-
同端口号 ( 80HTTP的 , 443HTTPS的 )
如果不同源就会产生跨域
跨域问题的产生 ( 以下任意一点不同就会跨域 )
-
协议不一样
-
端口不一样
-
ip地址不一样
-
以文件访问 ( 不同的文件资源也会跨域 )
跨域问题的解决
1.前端解决 ( JSONP ) ( 需要后端给的是JSONP的接口 )
2.后端解决 ( 在对应的响应头进行设置 )
3.使用服务器代理 ( proxy )
4.使用websocket ( 走的不是http协议 )
JSONP
概述 :
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题 .
然后它是通过script标签不受跨域影响的特性来解决的 ,
<script>// JSONP就是利用script标签不会受跨域的影响来实现的,通过服务器的回调函数拿到数据再传过来// 它会自动执行你传入的回调函数并将结果传递给这个函数,res里面就会执行完这个数据function callback(res) {console.log(res)} </script> <!-- wd表示关键词 cb表示回调函数 --> <script src="https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=callback"> </script>
// 封装jsonp export const jsonp = (url, params, callbackName, callback) => {// 遍历参数,判断url内是否存在?for (let key in params) {if (url.includes('?')) {url += `&${key}=${params[key]}`} else {url += `?${key}=${params[key]}`}}// 随机生成一个函数名并赋给回调函数let fnName = 'fn' + Date.now()window[fnName] = callback// 将回调函数的名字拼接到url上url += `&${callbackName}=${fnName}`// 创建一个script标签在页面上并设置url属性let script = document.createElement('script')script.src = urldocument.body.appendChild(script)// 创建后触发onload加载事件script.onload = () => {// 加载完成后删除函数和script标签delete window[fnName]script.remove()} }
<script type="module">//导入jsonp import { jsonp } from './00.js'var ul=document.querySelector('ul')//给input框添加输入触发事件 document.querySelector('input').oninput = function () {//调用 jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su', {wd: this.value},'cb', (res) => {console.log(res)ul.innerHTML=''//渲染 res.s.forEach((item)=>{ul.innerHTML+=`<li>${item}</li> `})})} </script>
// 封装一个jsonp的promise方法 // url地址,参数,回调函数名称 export const jsonp = (url, params, callbackName) => {// 直接返回一个promise对象return new Promise((resolve, reject) => {// 遍历参数,判断url是否存在'?',没有就加上,有就加上后面的数据for (let key in params) {if (url.includes('?')) {url += `&${key}=${params[key]}`} else {url += `?${key}=${params[key]}`}}// 随机生成函数名let fnName = 'fn' + Date.now() + Math.ceil(Math.random() * 21)// 把函数加到window上window[fnName] = resolve// 拼接url地址url += `&${callbackName}=${fnName}`// 创建script标签并设置url属性再加到页面上let script = document.createElement('script')script.src = urldocument.body.append(script)// 加载完成后就删除函数和标签script.onload = () => {delete window[fnName]script.remove()}// 有报错就执行rejectscript.onerror = () => {reject()}}) }
<input type="text"> <ul></ul> <script type="module">// 导入jsonp import { jsonp } from './00.js'let ul = document.querySelector('ul')// 给input添加输入就触发事件 document.querySelector('input').oninput = function () {// 调用方法 jsonp('https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su', {wd: this.value}, 'cb').then((res) => {console.log(res)// 渲染 ul.innerHTML = ''res.s.forEach((item) => {ul.innerHTML += `<li>${item}</li> `})})} </script>