如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
如何将表单的所有元素转换为JavaScript对象?
我希望有某种方法从表单自动构建JavaScript对象,而不必遍历每个元素。我不希望使用$('#formid').serialize();返回的字符串;,我也不希望$('#formid').serializeArray()返回映射;
当前回答
Tobias上面的解决方案是正确的,但是正如评论者@macek所指出的,它不处理foo[bar]类型的输入并将其拆分为子对象。
这是一个PHP独有的特性,但我仍然觉得能够在JavaScript中生成相同的结构非常有用。
我只是修改了上面托拜厄斯的代码,所以所有的功劳都归于他。这可能会变得更干净,但我只是在五分钟内把它搅拌起来,并认为它可能有用。
此时它不处理多维数组或数字索引数组。也就是说,它只能使用foo[bar]而不能使用foo[]。
jQuery.fn.serializeObjectPHP = function()
{
var o = {};
var re = /^(.+)\[(.*)\]$/;
var a = this.serializeArray();
var n;
jQuery.each(a, function() {
var name = this.name;
if ((n = re.exec(this.name)) && n[2]) {
if (o[n[1]] === undefined) {
o[n[1]] = {};
o[n[1]][n[2]] = this.value || '';
} else if (o[n[1]][n[2]] === undefined) {
o[n[1]][n[2]] = this.value || '';
} else {
if(!o[n[1]][n[2]].push) {
o[n[1]][n[2]] = [ o[n[1]][n[2]] ];
}
o[n[1]][n[2]].push(this.value || '');
}
} else {
if (n && !n[2]) {
name = n[1];
}
if (o[name] !== undefined) {
if (!o[name].push) {
o[name] = [o[name]];
}
o[name].push(this.value || '');
} else {
o[name] = this.value || '';
}
}
});
return o;
};
其他回答
由于XSS攻击和可能存在的其他问题,我不会在现场网站上使用此功能,但下面是一个快速示例:
$("#myform").submit(function(){
var arr = $(this).serializeArray();
var json = "";
jQuery.each(arr, function(){
jQuery.each(this, function(i, val){
if (i=="name") {
json += '"' + val + '":';
} else if (i=="value") {
json += '"' + val.replace(/"/g, '\\"') + '",';
}
});
});
json = "{" + json.substring(0, json.length - 1) + "}";
// do something with json
return false;
});
将任何东西变成对象(未经单元测试)
<script type="text/javascript">
string = {};
string.repeat = function(string, count)
{
return new Array(count+1).join(string);
}
string.count = function(string)
{
var count = 0;
for (var i=1; i<arguments.length; i++)
{
var results = string.match(new RegExp(arguments[i], 'g'));
count += results ? results.length : 0;
}
return count;
}
array = {};
array.merge = function(arr1, arr2)
{
for (var i in arr2)
{
if (arr1[i] && typeof arr1[i] == 'object' && typeof arr2[i] == 'object')
arr1[i] = array.merge(arr1[i], arr2[i]);
else
arr1[i] = arr2[i]
}
return arr1;
}
array.print = function(obj)
{
var arr = [];
$.each(obj, function(key, val) {
var next = key + ": ";
next += $.isPlainObject(val) ? array.print(val) : val;
arr.push( next );
});
return "{ " + arr.join(", ") + " }";
}
node = {};
node.objectify = function(node, params)
{
if (!params)
params = {};
if (!params.selector)
params.selector = "*";
if (!params.key)
params.key = "name";
if (!params.value)
params.value = "value";
var o = {};
var indexes = {};
$(node).find(params.selector+"["+params.key+"]").each(function()
{
var name = $(this).attr(params.key),
value = $(this).attr(params.value);
var obj = $.parseJSON("{"+name.replace(/([^\[]*)/, function()
{
return '"'+arguments[1]+'"';
}).replace(/\[(.*?)\]/gi, function()
{
if (arguments[1].length == 0)
{
var index = arguments[3].substring(0, arguments[2]);
indexes[index] = indexes[index] !== undefined ? indexes[index]+1 : 0;
return ':{"'+indexes[index]+'"';
}
else
return ':{"'+escape(arguments[1])+'"';
})+':"'+value.replace(/[\\"]/gi, function()
{
return "\\"+arguments[0];
})+'"'+string.repeat('}', string.count(name, ']'))+"}");
o = array.merge(o, obj);
});
return o;
}
</script>
测试输出:
$(document).ready(function()
{
console.log(array.print(node.objectify($("form"), {})));
console.log(array.print(node.objectify($("form"), {selector: "select"})));
});
on
<form>
<input name='input[a]' type='text' value='text'/>
<select name='input[b]'>
<option>select</option>
</select>
<input name='otherinput[c][a]' value='a'/>
<input name='otherinput[c][]' value='b'/>
<input name='otherinput[d][b]' value='c'/>
<input name='otherinput[c][]' value='d'/>
<input type='hidden' name='anotherinput' value='hidden'/>
<input type='hidden' name='anotherinput' value='1'/>
<input type='submit' value='submit'/>
</form>
将产生:
{ input: { a: text, b: select }, otherinput: { c: { a: a, 0: b, 1: d }, d: { b: c } }, anotherinput: 1 }
{ input: { b: select } }
此代码适用于我:
var data = $('#myForm input, #myForm select, #myForm textarea').toArray().reduce(function (m, e) {
m[e.name] = $(e).val();
return m;
}, {});
【2020年更新】
在vanilla js中有一个简单的oneliner,它利用了fromEntries(一如既往,请检查浏览器支持):
Object.fromEntries(new FormData(form))
所以我使用了公认的答案,发现了一个主要缺陷。它不支持以下输入数组:
<input type="checkbox" name="array[]" value="1"/>
<input type="checkbox" name="array[]" value="2"/>
<input type="checkbox" name="array[]" value="3"/>
这一小改动应该可以解决以下问题:
function objectifyForm(inp){
var rObject = {};
for (var i = 0; i < inp.length; i++){
if(inp[i]['name'].substr(inp[i]['name'].length - 2) == "[]"){
var tmp = inp[i]['name'].substr(0, inp[i]['name'].length-2);
if(Array.isArray(rObject[tmp])){
rObject[tmp].push(inp[i]['value']);
} else{
rObject[tmp] = [];
rObject[tmp].push(inp[i]['value']);
}
} else{
rObject[inp[i]['name']] = inp[i]['value'];
}
}
return rObject;
}
记住将$(this).serializeArray()的输出传递给它;否则它不会起作用。