【问题标题】:Easier way to transform FormData into query string将 FormData 转换为查询字符串的更简单方法
【发布时间】:2017-08-16 06:41:37
【问题描述】:

我正在通过XMLHttpRequest 发送一个 POST 请求,并将数据输入到 HTML 表单中。不受 JavaScript 干扰的表单会提交编码为application/x-www-form-urlencoded 的数据。

使用 XMLHttpRequest,我想通过 FormData API 发送数据,但由于它将数据视为编码为 multipart/form-data,因此它不起作用。因此,我需要将数据作为查询字符串,正确转义,写入XMLHttpRequest 的发送方法。

addEntryForm.addEventListener('submit', function(event) {
    // Gather form data
    var formData = new FormData(this);
    // Array to store the stringified and encoded key-value-pairs.
    var parameters = []
    for (var pair of formData.entries()) {
        parameters.push(
            encodeURIComponent(pair[0]) + '=' +
            encodeURIComponent(pair[1])
        );
    }

    var httpRequest = new XMLHttpRequest();
    httpRequest.open(form.method, form.action);

    httpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    httpRequest.onreadystatechange = function() {
        if (httpRequest.readyState === XMLHttpRequest.DONE) {
            if (httpRequest.status === 200) {
                console.log('Successfully submitted the request');
            } else {
                console.log('Error while submitting the request');
            }
        }
    };

    httpRequest.send(parameters.join('&'));

    // Prevent submitting the form via regular request
    event.preventDefault();
});

现在,for ... of 循环等的整个事情似乎有点令人费解。有没有更简单的方法将FormData 转换为查询字符串?或者我可以用不同的编码发送 FormData 吗?

【问题讨论】:

  • @Andreas 这是缩短代码的一种方法,因此请随意添加它作为答案。

标签: javascript xmlhttprequest form-data


【解决方案1】:

如果您可以使用JQuery,您只需在您的form 对象上调用.serialize() 函数,如下所示:

function getQueryString() {
  var str = $( "form" ).serialize();
  console.log(str);
}

$( "#cmdTest" ).on( "click", getQueryString );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<form>
  <select name="list1">
    <option>opt1</option>
    <option>opt2</option>
  </select>
 
  <br>
  <input type="text" name="txt1" value="valWith%Special&Char$">
  <br>
  <input type="checkbox" name="check" value="check1" id="ch1">
  <label for="ch1">check1</label>
  <input type="checkbox" name="check" value="check2" checked="checked" id="ch2">
  <label for="ch2">check2</label>
 
  <br>
  <input type="radio" name="radio" value="radio1" checked="checked" id="r1">
  <label for="r1">radio1</label>
  <input type="radio" name="radio" value="radio2" id="r2">
  <label for="r2">radio2</label>
</form>
  
<button id="cmdTest">Get queryString</button>

注意:它还对数据进行编码以在 url 请求中使用它

希望对你有帮助,再见。

【讨论】:

  • JQuery 最终会做类似的事情。我追求的是算法实现,而不是隐藏复杂性的方法。
【解决方案2】:

您要求更简单的解决方案...
for 循环是遍历集合的最简单方法 - 恕我直言。

但是如果你使用spread operator/syntax (...),还有一个更短的版本

展开语法允许表达式在以下位置展开 多个参数(用于函数调用)或多个元素(用于 数组文字)或多个变量(用于解构赋值) 预计。

您的 for...of 循环可以替换为:

let parameters = [...formData.entries()] // expand the elements from the .entries() iterator into an actual array
                     .map(e => encodeURIComponent(e[0]) + "=" + encodeURIComponent(e[1]))  // transform the elements into encoded key-value-pairs

【讨论】:

  • 虽然我接受了这个答案,但我确实认为最好像我在问题中那样编写一个循环,因为它更易于阅读。
【解决方案3】:

你可以使用URLSearchParams

const queryString = new URLSearchParams(new FormData(myForm)).toString()

【讨论】:

  • 好主意,除了当前的浏览器支持。 caniuse.com/#feat=urlsearchparams
  • 为什么需要.toString()
  • @o-t-w 因为new URLSeachParams() 返回一个对象,所以您需要将其转换为字符串才能使用它;)
  • @o-t-w,如果你不想使用.toString(),试试const queryString = `new URLSearchParams(new FormData(myForm))`;
  • 如果像我这样的人在 Edge 中发现错误,请使用 Lodash 并将代码更新到这会有所帮助。 new URLSearchParams(_.toArray(new FormData(myForm))).toString()。可怜的 MS Edge!
猜你喜欢
  • 2015-12-15
  • 2013-09-16
  • 2010-12-21
  • 1970-01-01
  • 2013-05-31
  • 2014-03-05
  • 1970-01-01
  • 2017-06-09
  • 1970-01-01
相关资源
最近更新 更多