最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • JSONP方法解决跨域问题

    正文概述 掘金(我的吗吗咪呀)   2021-04-07   435

    什么是同源策略

    源:协议、域名、端口号。
    在数据响应回来时浏览器会检测请求数据的源与发送请求的HTML页面的源是否一致。
    维基百科的解释如下图,详细讲解可参阅维基百科-同源策略

    JSONP方法解决跨域问题 需要注意的一点是,直接在浏览器中打开访问链接,相当于就是直接访问,是能看到数据。但是,当从一个页面发送请求访问时,会判断是不是跨域,如果是跨域,请求其实也是发送出去了的,服务器也响应了,但是响应回来后被浏览器拦截了,因为浏览器的安全策略中有个同源策略。

    JSONP(JSON+Padding)方法及其原理

    JSONP方法:利用script标签不受同源策略限制的特性,在HTML页面中动态生成script标签,利用script标签的src属性访问服务器端,服务器端会返回一个函数的调用(fuName(返回的数据)),并将响应数据放在回调函数的参数里,HTML页面通过回调函数的参数获取响应数据。
    以下提供两个我看过的讲解jsonp的视频:
    YouTube-跨域讲解了jsonp方法在HTML页面以及服务器端的数据交互,
    YouTube-jsonp讲解了jsonp方法访问某外部接口时的函数调用。
    注:img、link和script标签不受同源策略限制,允许跨域加载。
    我的讲述若有不明确的地方,也可参考博客,下图就是该博客的部分内容截图。

    JSONP方法解决跨域问题

    代码实现

    jsonp方法代码实现

    以城市接口wis.qq.com/city/like 为例,该接口所需参数见下图,该图来源博客

    JSONP方法解决跨域问题 第一步,要直接访问一次接口来查看回调函数名是什么;
    这个接口是在腾讯天气的地址搜索栏里调用的,所以我们在搜索框中调用一次该接口,查看网络中的请求头信息,发现回调函数名称是callback,如下图:

    JSONP方法解决跨域问题 我们就可以确定访问的地址应是:wis.qq.com/city/like?s…
    第二步,此次调用以香港为例。

    function getData(data) {
            let script = document.getElementById("jsonp")
            script.parentNode.removeChild(script)  //移除该新创的节点
            console.log(data)
        }
    
        // 创建script节点
        let script = document.createElement("script")
        script.id = "jsonp"
        script.src = "https://wis.qq.com/city/like?source=pc&city=香港&callback=getData"
        // 将script节点添加到DOM树中,否则该节点不会生效
        document.body.appendChild(script)
    

    如下图,便是此次调用接口的请求头和响应数据。

    JSONP方法解决跨域问题

    JSONP方法解决跨域问题

    jsonp函数封装

    按照上面的办法,每次调用jsonp都要重复上述代码,很不方便,所以我们可以进一步地封装该方法。
    按照上述思路,我们一共需要四个参数,访问url、访问参数、接口定义的回调函数参数名、回调函数参数体。
    (注:不同接口的回调函数参数名不同,我见到的大部分接口回调函数参数名都是callback,也有例外,如百度网搜索框的回调函数参数名是cb,如下图 JSONP方法解决跨域问题) 封装后的代码如下:

    /*
        url: 访问链接
        params: 参数名/参数值组成的json格式的数据
        cbName: 访问接口时规定的回调函数参数名
        cbFunction: 回调函数具体函数体
         */
        function jsonp(url, params, cbName, cbFunction) {
            let strParams = ""
            // 遍历json格式的参数,组合为符合格式的字符串
            for (let key in params) {
                // 经过最后一次遍历时最后一个参数末尾后会多一个&,后接回调函数参数
                strParams += key + "=" + params[key] + "&"
            }
            // Math.random(): 返回 0 ~ 1 之间的随机数,降低同时调用多个jsonp 请求时回调函数名称的重复率
            let fnName = cbName + Math.random().toString().replace('.', '')
            // 创建script节点
            let script = document.createElement("script")
            script.src = url + "?" + strParams + cbName + "=" + fnName
            // 将script节点添加到DOM树中,否则该节点不会生效
            document.body.appendChild(script)
            // 将回调函数加入全局作用域
            window[fnName] = cbFunction
            // 当这个 script 标签加载完毕时将其移出
            script.onload = () => script.parentNode.removeChild(script)
        }
    

    调用方式如下:

    jsonp("https://wis.qq.com/city/like", {
                "source": "pc",
                "city": "香港",
            }, "callback",
            (data) => console.log(data))
    

    需注意的问题

    1. 回调函数一定要放在全局作用域,因为服务端接收到回调函数后会返回页面中的script中去找,如果不写在全局作用域中根本找不到;
    2. 不同接口的回调函数参数名不同,封装函数的话这个地方需要单独作为参数。

    起源地下载网 » JSONP方法解决跨域问题

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元