表单序列化javascript(没有框架)

Rus*_*wer 118 javascript forms serialization

想知道javascript中是否有一个函数没有jquery或任何允许我序列化表单并访问序列化版本的框架?

Art*_*jev 150

这是纯JavaScript方法:

var form = document.querySelector('form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
Run Code Online (Sandbox Code Playgroud)

虽然它似乎只适用于POST请求.

https://developer.mozilla.org/en-US/docs/Web/API/FormData

  • 注意,这会发送multipart,这对于一些简单的REST服务(即feather-mongoDB)效果不佳 (10认同)
  • 注意这只是IE10及以上版本,但是一个很好的解决方案 (4认同)
  • 请注意,您可能必须在 `req.send(data);` 之前使用 `req.open("POST", "<your-url>");` 否则我会收到错误 `InvalidStateError: XMLHttpRequest state must be OPENED。 ` 在 Firefox 66 上。它应该可以与其他请求一起使用,就像 PUT 一样,只需将 POST 替换为 PUT。 (2认同)
  • 仍然可以通过 GET 方法提交 frm。 (2认同)

gle*_*ebm 70

如果您的目标浏览器支持URLSearchParamsAPI(最新浏览器)和FormData(formElement)构造函数(除Edge之外的最新浏览器),请使用以下命令:

new URLSearchParams(new FormData(formElement)).toString()
Run Code Online (Sandbox Code Playgroud)

对于支持URLSearchParams但不支持FormData(formElement)构造函数的浏览器,请使用此FormData polyfill和:

new URLSearchParams(Array.from(new FormData(formElement))).toString()
Run Code Online (Sandbox Code Playgroud)

对于旧版浏览器(例如IE 10),请使用FormData polyfill,Array.from必要时使用polyfill,以及这个单行:

var form = document.querySelector('form');
var out = document.querySelector('output');

function updateResult() {
  try {
    out.textContent = new URLSearchParams(Array.from(new FormData(form)));
    out.className = '';
  } catch (e) {
    out.textContent = e;
    out.className = 'error';
  }
}

updateResult();
form.addEventListener('input', updateResult);
Run Code Online (Sandbox Code Playgroud)


Lus*_*ian 34

微型from-serialize库不依赖于框架.除此之外,您还需要自己实现序列化功能.(虽然重量为1.2千字节,为什么不使用它呢?)

  • 请包含一些代码,而不仅仅是指向库的链接。如果库是开源的,您应该能够复制相关代码。 (5认同)
  • 这是完美的。但是不得不在代码的输入部分添加一个`case 'email':` (2认同)

Joh*_*ano 34

function serialize (form) {
    if (!form || form.nodeName !== "FORM") {
            return;
    }
    var i, j, q = [];
    for (i = form.elements.length - 1; i >= 0; i = i - 1) {
        if (form.elements[i].name === "") {
            continue;
        }
        switch (form.elements[i].nodeName) {
            case 'INPUT':
                switch (form.elements[i].type) {
                    case 'text':
                    case 'tel':
                    case 'email':
                    case 'hidden':
                    case 'password':
                    case 'button':
                    case 'reset':
                    case 'submit':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'checkbox':
                    case 'radio':
                        if (form.elements[i].checked) {
                                q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        }                                               
                        break;
                }
                break;
                case 'file':
                break; 
            case 'TEXTAREA':
                    q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                    break;
            case 'SELECT':
                switch (form.elements[i].type) {
                    case 'select-one':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                    case 'select-multiple':
                        for (j = form.elements[i].options.length - 1; j >= 0; j = j - 1) {
                            if (form.elements[i].options[j].selected) {
                                    q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].options[j].value));
                            }
                        }
                        break;
                }
                break;
            case 'BUTTON':
                switch (form.elements[i].type) {
                    case 'reset':
                    case 'submit':
                    case 'button':
                        q.push(form.elements[i].name + "=" + encodeURIComponent(form.elements[i].value));
                        break;
                }
                break;
            }
        }
    return q.join("&");
}
Run Code Online (Sandbox Code Playgroud)

资料来源:http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js

  • 我已经将这样的修改版本添加到https://gist.github.com/brettz9/7147458(还有其他一些改进) (3认同)
  • 不一定要提交提交按钮,永远不应该提交重置按钮,只有用于提交的按钮,在这种情况下被视为提交按钮.参见[HTML5 4.10.22表格提交](http://www.w3.org/html/wg/drafts/html/CR/forms.html#concept-form-submit). (3认同)

Sim*_*ger 23

这是TibTibs的略微修改版本:

function serialize(form) {
    var field, s = [];
    if (typeof form == 'object' && form.nodeName == "FORM") {
        var len = form.elements.length;
        for (i=0; i<len; i++) {
            field = form.elements[i];
            if (field.name && !field.disabled && field.type != 'file' && field.type != 'reset' && field.type != 'submit' && field.type != 'button') {
                if (field.type == 'select-multiple') {
                    for (j=form.elements[i].options.length-1; j>=0; j--) {
                        if(field.options[j].selected)
                            s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.options[j].value);
                    }
                } else if ((field.type != 'checkbox' && field.type != 'radio') || field.checked) {
                    s[s.length] = encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value);
                }
            }
        }
    }
    return s.join('&').replace(/%20/g, '+');
}
Run Code Online (Sandbox Code Playgroud)

禁用的字段将被丢弃,名称也会进行URL编码.在返回字符串之前,正则表达式替换%20个字符只发生一次.

查询字符串与jQuery的$ .serialize()方法的结果形式相同.

  • +1用于花时间改进代码.当人们发现我的缺点时,我很享受,因为这是一个很好的学习机会.+1,以保持它看起来不错.-1因为我不能给+2 =( (6认同)

Tib*_*ibs 12

我从Johndave Decano的答案开始.

这应该可以解决对其功能的回复中提到的一些问题.

  1. 用+符号替换%20.
  2. 提交/按钮类型仅在单击提交表单时才会提交.
  3. 重置按钮将被忽略.
  4. 代码对我来说似乎是多余的,因为无论字段类型如何,代码都基本相同.更不用说与'tel'和'email'等HTML5字段类型不兼容,因此我使用switch语句删除了大部分细节.

如果按钮类型没有名称值,则仍会忽略它们.

function serialize(form, evt){
    var evt    = evt || window.event;
    evt.target = evt.target || evt.srcElement || null;
    var field, query='';
    if(typeof form == 'object' && form.nodeName == "FORM"){
        for(i=form.elements.length-1; i>=0; i--){
            field = form.elements[i];
            if(field.name && field.type != 'file' && field.type != 'reset'){
                if(field.type == 'select-multiple'){
                    for(j=form.elements[i].options.length-1; j>=0; j--){
                        if(field.options[j].selected){
                            query += '&' + field.name + "=" + encodeURIComponent(field.options[j].value).replace(/%20/g,'+');
                        }
                    }
                }
                else{
                    if((field.type != 'submit' && field.type != 'button') || evt.target == field){
                        if((field.type != 'checkbox' && field.type != 'radio') || field.checked){
                            query += '&' + field.name + "=" + encodeURIComponent(field.value).replace(/%20/g,'+');
                        }   
                    }
                }
            }
        }
    }
    return query.substr(1);
}
Run Code Online (Sandbox Code Playgroud)

这就是我目前使用此功能的方式.

<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
Run Code Online (Sandbox Code Playgroud)

  • 为精心重构的代码+1.-1用于忽略禁用的字段,这些字段不应出现在查询字符串中.非常优雅的语句+1,避免重复计算表单元素.总计:+1 :-)谢谢! (6认同)

mol*_*son 10

如果您需要使用json格式的POST提交表单"myForm",您可以:

const formEntries = new FormData(myForm).entries();
const json = Object.assign(...Array.from(formEntries, ([x,y]) => ({[x]:y})));
fetch('/api/foo', {
  method: 'POST',
  body: JSON.stringify(json)
});
Run Code Online (Sandbox Code Playgroud)

第二行从如下数组转换:

[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]
Run Code Online (Sandbox Code Playgroud)

...进入常规对象,如:

{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }
Run Code Online (Sandbox Code Playgroud)

...它通过将mapFn传入Array.from()来完成此转换.此mapFn应用于每个["a","b"]对并将它们转换为{"a":"b"},以便数组包含大量对象,每个对象只有一个属性.mapFn使用"destructuring"来获取该对的第一和第二部分的名称,并且它还使用ES6"ComputedPropertyName"来设置mapFn返回的对象中的属性名称(这就是为什么说"[ x]:"而不仅仅是"x:某种东西".

然后将所有这些单个属性对象传递给Object.assign()函数的参数,该函数将所有单个属性对象合并为具有所有属性的单个对象.

Array.from():https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

参数解构:https: //simonsmith.io/destructuring-objects-as-function-parameters-in-es6/

有关计算属性名称的更多信息: 变量作为JavaScript对象文字中的属性名称?

  • 您可以使用新方法 Object.fromEntries(new FormData(myFormElement)) 序列化表单。 (3认同)

Dav*_*mon 8

适用于所有浏览器.

const formSerialize = formElement => {
  const values = {};
  const inputs = formElement.elements;

  for (let i = 0; i < inputs.length; i++) {
    values[inputs[i].name] = inputs[i].value;
  }
  return values;
}

const dumpValues = form => () => {
  
  const r = formSerialize(form);
  console.log(r);
  console.log(JSON.stringify(r));
}

const form = document.querySelector('form');

dumpValues(form)();

form.addEventListener('change',dumpValues(form));
Run Code Online (Sandbox Code Playgroud)
<form action="/my-handling-form-page" method="post">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="user_name" value="John">
  </div>
  <div>
    <label for="mail">E-mail:</label>
    <input type="email" id="mail" name="user_mail" value="john@jonhson.j">
  </div>
  <div>
    <label for="interests">Interest:</label>
    <select required=""  id="interests" name="interests">
      <option value="" selected="selected">- None -</option>
      <option value="drums">Drums</option>
      <option value="js">Javascript</option>
      <option value="sports">Sports</option>
      <option value="trekking">Trekking</option>
    </select>
  </div>
  <div>
    <label for="msg">Message:</label>
    <textarea id="msg" name="user_message">Hello My Friend</textarea>
  </div>
</form>
Run Code Online (Sandbox Code Playgroud)


小智 6

HTMLElement.prototype.serialize = function(){
    var obj = {};
    var elements = this.querySelectorAll( "input, select, textarea" );
    for( var i = 0; i < elements.length; ++i ) {
        var element = elements[i];
        var name = element.name;
        var value = element.value;

        if( name ) {
            obj[ name ] = value;
        }
    }
    return JSON.stringify( obj );
}
Run Code Online (Sandbox Code Playgroud)

要像这样使用:

var dataToSend = document.querySelector("form").serialize();
Run Code Online (Sandbox Code Playgroud)

我希望我有所帮助.

  • 不适用于复选框.在这里,您必须明确检查输入类型. (3认同)

CAO*_*ley 5

如果您要序列化事件的输入。这是我使用的纯JavaScript方法。

// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
  data[input.name] = input.value;
});
Run Code Online (Sandbox Code Playgroud)

数据将是输入的JavaScript对象。

  • 这应该适用于大多数元素。不过绝对不是textarea / select (2认同)

Ste*_*bos 5

一个重构版本的@ SimonSteinberger的代码使用较少的变量并利用forEach循环的速度(比fors 快一点)

function serialize(form) {
    var result = [];
    if (typeof form === 'object' && form.nodeName === 'FORM')
        Array.prototype.slice.call(form.elements).forEach(function(control) {
            if (
                control.name && 
                !control.disabled && 
                ['file', 'reset', 'submit', 'button'].indexOf(control.type) === -1
            )
                if (control.type === 'select-multiple')
                    Array.prototype.slice.call(control.options).forEach(function(option) {
                        if (option.selected) 
                            result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(option.value));
                    });
                else if (
                    ['checkbox', 'radio'].indexOf(control.type) === -1 || 
                    control.checked
                ) result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(control.value));
        });
        return result.join('&').replace(/%20/g, '+');
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这可以通过非常简单的函数来完成,如下所示

function serialize(form) {
        let requestArray = [];
        form.querySelectorAll('[name]').forEach((elem) => {
            requestArray.push(elem.name + '=' + elem.value);
        });
        if(requestArray.length > 0)
            return requestArray.join('&');
        else
            return false;
    }

 serialized = serialize(document.querySelector('form'))
  console.log(serialized);
Run Code Online (Sandbox Code Playgroud)
<form>

  <input type='text' name='fname' value='Johne'/>
  <input type='text' name='lname' value='Doe'/>
  <input type='text' name='contact[]' value='99999999'/>
  <input type='text' name='contact[]' value='34423434345'/>

</form>
Run Code Online (Sandbox Code Playgroud)