jQuery ajax 方法 data 参数默认 encode 失败的 bug

使用 jQuery ajax 方法调用异步接口时 data 参数默认会被添加转码 encodeURIComponent,如下:

$.ajax({
    url: 'http://your.domain.com/action',
    dataType: 'jsonp',
    data: {
        spaces: 'a b',
        other: '&'
    }
})

上面的代码会向 http://your.domain.com/action?spaces=a+b&other=%26 发送 get 请求,奇怪的是参数中的 & 被正确转码成 %26,但是 被转成了 + 而不是 %20

看看正确的转码结果长啥样

encodeURIComponent('&') // => "%26"
encodeURIComponent(' ') // => "%20"

既然 data 参数里面的 key,value 都要被 encodeURIComponent,那么出现这种情况只能去查 jQuery 源代码了。jQuery 会调用 $.param 方法来编码 data 参数,大概在 jQuery-1.7.2(7736) 行:

param: function( a, traditional ) {
    // ...
    } else {
        // If traditional, encode the "old" way (the way 1.3.2 or older
        // did it), otherwise encode params recursively.
        for ( var prefix in a ) {
            buildParams( prefix, a[ prefix ], traditional, add );
        }
    }

    // Return the resulting serialization
    return s.join( "&" ).replace( r20, "+" );
}

param 方法内部会再调用 buildParams 来把 data 对象键值对添加编码,一切都很正常

然饿最后一行 replace( r20, "+" ) 是什么鬼!r20 变量是内部的一个空白转义符的正则 /%20/g

这就有点意思了,为啥把正确的空格编码再转回 + 呢?

外事不决问 Google,搜索 why jquery ajax convert %20 to + 结果发现有一条 jQuery 官方的 github issue: Only change %20 to + for application/x-www-form-urlencoded

google-why-jquery-convert-space-to-plus

根据 issue 的描述大意是说 convert %20 to + 这个逻辑只应该在 POST 请求的时候做转换,而不是所有请求。我们的示例中的 jsonp 刚好是 get 请求

继续往下看找到了一个 commit(60453ce) 修复了这个问题

jquery-param-encode-bug

注意一点,我们并不能简单的在 data 对象传入的时候手动添加 encodeURIComponent

$.ajax({
    url: 'http://your.domain.com/action',
    dataType: 'jsonp',
    data: {
        // 错误的做法
        spaces: encodeURIComponent('a b'),
        other: '&'
    }
})

如果 spaces 参数有别的应该被正常编码的字符串,这样会导致正常的被编码的字符被 两次 encodeURIComponent。所以要正确解决这个问题需要修改 jQuery 源代码,这个可以参考上面的那个 fix commit

博客原文同步更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
jQuery是一种JavaScript库,ajax是一种能够向服务器端发送和接收请求的技术。在Web开发中,ajax技术可以让页面在不刷新的情况下向服务器请求数据,使得页面更加丰富和动态。 下面就是一个jQuery ajax请求的实例: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jQuery Ajax Request</title> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <!--需要引入jQuery库--> <script> $(document).ready(function() { $("#btn").click(function() { //当按钮被点击时 $.ajax({ url: "data.php", //请求地址 data: {"name":"Tom", "age":18}, //请求参数 type: "post", //请求方式 dataType: "json", //返回值类型 success: function(result) { //请求成功时的回调函数 $("#result").html(result.name + "今年" + result.age + "岁"); //将返回值显示在页面上 }, error: function() { //请求失败时的回调函数 alert("请求失败"); } }); }); }); </script> </head> <body> <button id="btn">请求数据</button><br><br> <div id="result"></div> </body> </html> ``` 在这个实例中,我们使用了jQueryajax函数,这个函数有很多参数,其中一些常用的参数包括: - url:请求地址; - data:请求参数; - type:请求方式(常用的有get和post); - dataType:返回值类型(常用的有json和html); - success:请求成功时的回调函数; - error:请求失败时的回调函数。 在按钮被点击时,我们向服务器请求数据,服务器通过data.php来处理请求,并返回一个json格式的数据: ```php <?php $name = $_POST["name"]; $age = $_POST["age"]; $result = array("name" => $name, "age" => $age); echo json_encode($result); ?> ``` 当请求成功时,我们将返回的数据解析出来,并将其显示在页面上。如果请求失败,我们就弹出一个提示框。通过这个实例,我们可以学习到如何使用jQuery来进行ajax请求,以及如何处理请求成功和失败的情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值