跨域及解决方法-jsonp

什么是跨域

简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交和获取内容。由于安全原因,跨域访问是被各大浏览器所默认禁止的。

协议、ip(域名)、端口号 三者之中只要有一个不一样就是跨域
比如在http://www.xxx.com:80中调用下面三个都是跨域

http://mail.xxx.com:80 跨域(域名不同)
https://www.xxx.com:80 跨域(协议不同)
http://www.xxx.com:8080 跨域(端口不同)

如何解决跨域

jsonp

核心原理: 利用了 href 和 src 属性能够跨域请求数据的特性。
但是要注意JSONP只支持GET请求,不支持POST请求。

比如在我们学习JQuery时,要使用JQuery需要先引入JQuery文件,我们当时就是使用< script>标签来引入的,这就是使用jsonp来实现跨域请求的一个案例

script标签需要请求服务器的一个地址,该地址能够返回一个函数调用的字符串,该字符串会在html页面中被当成函数调用来执行,函数字符串中的内容就是服务器端给浏览器端返回的数据

案例

例子:使用express来搭建一个服务器,并启动服务

const app = require('express')()

app.listen(3000, ()=>{
  console.log('running....');
})
app.get('/jsonp',(req,res)=>{
  // abc()函数字符串中的内容就是服务器返回给客户端的数据
  res.send('abc()')
})
app.get('/bbb',(req,res)=>{
  console.log(req.query);
  res.send('abc({type:'text',age:12})')
})

再创建一个html文件,在页面上没有特殊指定,默认使用get请求

<script src="http://localhost:3000/jsonp"></script>

我们可以看到,请求成功了,也返回了数据,但是报错了
在这里插入图片描述
在这里插入图片描述
这是因为请求返回的数据会被当成js代码直接执行,而我们没有声明abc,因此会报错。但是如果我们在html页面中定义了abc的话

<script>
    function abc(){
      console.log('返回值直接执行');
    }
  </script>
  <script src="http://localhost:3000/jsonp"></script>

在这里插入图片描述
我们可以看到,我们只是定义了abc方法并没有执行它,但是该函数执行了,这是因为我们发送请求后,返回了abc(),这被当作js代码直接执行了

也可以利用它发送数据

<script>
    function abc(data){
      console.log(data);
    }
  </script>
  <script src="http://localhost:3000/bbb?type=12&age=11"></script>

在这里插入图片描述
在这里插入图片描述
服务器能接收到传递的数据,页面也能接受到服务器返回的数据

jsonp核心就是当我们请求一个服务器地址时,服务器需要返回给我们一个函数执行的模块,函数中的参数就是服务器返回给我们的数据

点击事件发送jsonp请求
<body>
  <button id="btn">发送jsonp</button>
  
<script>  
// 定义返回函数
function abc(data){
  console.log(data);
}

  document.querySelector('#btn').onclick = ()=>{
    // 创建script标签
    var script = document.createElement('script')
    // 为script标签添加srcshuxing并设置请求地址
    script.src = 'http://localhost:3000/bbb?type=12&age=11'
    // 将script标签添加到html页面中
    document.body.appendChild(script)
  }
</script>

在这里插入图片描述

函数的封装

如果想要调用其他服务器,只需要改变src即可,因此我们可以将它封装起来

初步封装

function abc(data){
  console.log(data);
}

  document.querySelector('#btn').onclick = ()=>{
    jsonp('http://localhost:3000/bbb?type=12&age=11')
  }
  //参数为请求的url地址
  function jsonp(url){
    // 创建script标签
    var script = document.createElement('script')
    // 为script标签添加srcshuxing并设置请求地址
    script.src = url
    // 将script标签添加到html页面中
    document.body.appendChild(script)
  }

完整封装: 将abc方法也放到封装函数中

我们在script中声明的函数和变量都是挂载到windows对象上的

document.querySelector('#btn').onclick = ()=>{
    jsonp('http://localhost:3000/bbb?type=12&age=11')
  }
  //参数为请求的url地址
  function jsonp(url){
    // 创建script标签
    var script = document.createElement('script')
    // 为script标签添加srcshuxing并设置请求地址
    script.src = url
    // 将script标签添加到html页面中
    document.body.appendChild(script)
    window.abc=(data)=>{
      console.log(data);
    }
  }

最终封装 将数据传递也封装进去

    // 参数1: 请求的服务器端的url地址
    // 参数2: 发送给服务器端的数据
    function jsonp (url, data) {
      // 1. 创建script标签
      var script = document.createElement('script')
      // 2. 为script标签增加src属性,设置请求地址
      // 判断data的数据类型,如果是对象则调用getparmas函数,如果不是则不需要调用
      if (typeof data === 'object') {
        data = getParams(data)
      }
      script.src = url + '?' + data
      // 3. 将script标签添加到html页面中
      document.body.appendChild(script)
      // 4. 将abc函数放在函数体内
      window.abc = function (data) {
        console.log(data)
      }
    }

    function getParams (obj) {
      var str = ''
      for (var k in obj) {
        str += k + '=' + obj[k] + '&'
      }
      str = str.slice(0, str.length - 1)
      return str
    }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值