สงสัยว่ามีฟังก์ชั่นใน javascript ที่ไม่มี jquery หรือเฟรมเวิร์กใด ๆ ที่อนุญาตให้ฉันจัดรูปแบบและเข้าถึงเวอร์ชันซีเรียล
สงสัยว่ามีฟังก์ชั่นใน javascript ที่ไม่มี jquery หรือเฟรมเวิร์กใด ๆ ที่อนุญาตให้ฉันจัดรูปแบบและเข้าถึงเวอร์ชันซีเรียล
คำตอบ:
ไลบรารีขนาดเล็กจากซีเรียลไลซ์ไม่ขึ้นอยู่กับเฟรมเวิร์ก นอกเหนือจากนั้นคุณจะต้องใช้ฟังก์ชันการทำให้เป็นอนุกรมด้วยตัวเอง (แม้ว่าน้ำหนัก 1.2 กิโลไบต์ทำไมไม่ใช้ล่ะ?)
case 'email':
ในส่วนอินพุตของรหัส
That's an error
นี่คือแนวทาง JavaScript ที่แท้จริง:
var form = document.querySelector('form');
var data = new FormData(form);
var req = new XMLHttpRequest();
req.send(data);
แม้ว่าดูเหมือนว่าจะใช้ได้กับคำขอ POST เท่านั้น
req.open("POST", "<your-url>");
ก่อนreq.send(data);
มิฉะนั้นฉันมีข้อผิดพลาดInvalidStateError: XMLHttpRequest state must be OPENED.
ใน Firefox 66 ควรทำงานร่วมกับคำขออื่น ๆ เช่น PUT คือคุณแทนที่ POST ด้วย PUT
หากคุณกำหนดเป้าหมายเบราว์เซอร์ที่รองรับURLSearchParams
API ( เบราว์เซอร์ล่าสุด ) และตัวFormData(formElement)
สร้าง ( เบราว์เซอร์ล่าสุด ) ให้ใช้สิ่งนี้:
new URLSearchParams(new FormData(formElement)).toString()
สำหรับเบราว์เซอร์ที่รองรับURLSearchParams
แต่ไม่ใช่ตัวFormData(formElement)
สร้างให้ใช้FormData polyfillนี้และรหัสนี้ (ใช้ได้ทุกที่ยกเว้น IE):
new URLSearchParams(Array.from(new FormData(formElement))).toString()
สำหรับเบราว์เซอร์รุ่นเก่า (เช่น IE 10) ให้ใช้FormData polyfillซึ่งเป็นArray.from
polyfill หากจำเป็นและรหัสนี้:
Array.from(
new FormData(formElement),
e => e.map(encodeURIComponent).join('=')
).join('&')
.toString()
จำเป็นจริงๆหรือ?
URLSearchParams
ใช่ การแปลงสตริงยังเกิดขึ้นโดยปริยายหากคุณแก้ไขหรือเพิ่มลงในสตริงซึ่งในกรณีtoString
นี้ไม่จำเป็นต้องมีการเรียกที่ชัดเจน
new FormData(formElement)
จะยังไม่รองรับ?
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("&");
}
ที่มา: http://code.google.com/p/form-serialize/source/browse/trunk/serialize-0.1.js
นี่คือ 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, '+');
}
ช่องที่ปิดใช้งานจะถูกละทิ้งและมีการเข้ารหัส URL ด้วย การแทนที่ Regex ของอักขระ% 20 จะเกิดขึ้นเพียงครั้งเดียวก่อนที่จะส่งคืนสตริง
สตริงแบบสอบถามอยู่ในรูปแบบที่เหมือนกันกับผลลัพธ์จากวิธี $ .serialize () ของ jQuery
form.nodeName.toLowerCase() == "form"
แทนform.nodeName == "FORM"
ฉันเริ่มต้นด้วยคำตอบจาก Johndave Decano
สิ่งนี้ควรแก้ไขปัญหาบางประการที่กล่าวถึงในการตอบกลับฟังก์ชันของเขา
ประเภทปุ่มจะยังคงถูกละเว้นหากไม่มีค่าชื่อ
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);
}
นี่คือวิธีที่ฉันกำลังใช้ฟังก์ชันนี้
<form onsubmit="myAjax('http://example.com/services/email.php', 'POST', serialize(this, event))">
หากคุณต้องการส่งแบบฟอร์ม "myForm" โดยใช้ POST ในรูปแบบ json คุณสามารถทำได้:
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)
});
บรรทัดที่สองแปลงจากอาร์เรย์เช่น:
[["firstProp", "firstValue"], ["secondProp", "secondValue"], ...and so on... ]
... ลงในวัตถุปกติเช่น:
{"firstProp": "firstValue", "secondProp": "secondValue", ...and so on ... }
... มันทำการแปลงโดยส่ง mapFn ไปยัง Array.from () mapFn นี้ใช้กับ ["a", "b"] แต่ละคู่และแปลงเป็น {"a": "b"} เพื่อให้อาร์เรย์มีออบเจ็กต์จำนวนมากที่มีคุณสมบัติเพียงหนึ่งรายการในแต่ละคู่ mapFn ใช้ "การทำลายโครงสร้าง" เพื่อรับชื่อของส่วนแรกและส่วนที่สองของคู่และยังใช้ ES6 "ComputedPropertyName" เพื่อตั้งชื่อคุณสมบัติในวัตถุที่ mapFn ส่งคืน (นี่คือเหตุผลที่ระบุว่า "[ x]: บางสิ่งบางอย่าง "แทนที่จะเป็นเพียง" x: something "
จากนั้นอ็อบเจ็กต์คุณสมบัติเดี่ยวทั้งหมดเหล่านี้จะถูกส่งผ่านไปยังอาร์กิวเมนต์ของฟังก์ชัน 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/
เพิ่มเติมเกี่ยวกับชื่อคุณสมบัติที่คำนวณได้ที่นี่: Variable as the property name in a JavaScript object literal?
ใช้ได้กับทุกเบราว์เซอร์
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));
<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>
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 );
}
วิธีใช้ดังนี้:
var dataToSend = document.querySelector("form").serialize();
ฉันหวังว่าฉันจะได้ช่วย
หากคุณต้องการจัดลำดับอินพุตในเหตุการณ์ นี่เป็นวิธี JavaScript ที่แท้จริงที่ฉันใช้
// serialize form
var data = {};
var inputs = [].slice.call(e.target.getElementsByTagName('input'));
inputs.forEach(input => {
data[input.name] = input.value;
});
ข้อมูลจะเป็นวัตถุ JavaScript ของอินพุต
โค้ดของ @ SimonSteinberger รุ่น refactored โดยใช้ตัวแปรน้อยกว่าและใช้ประโยชน์จากความเร็วของforEach
ลูป (ซึ่งเร็วกว่าfor
s เล็กน้อย)
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, '+');
}
ฉันปรับโครงสร้างคำตอบของ TibTibs เป็นสิ่งที่อ่านได้ชัดเจนกว่ามาก มันยาวขึ้นเล็กน้อยเนื่องจากความกว้าง 80 อักขระและความคิดเห็นเล็กน้อย
นอกจากนี้ยังละเว้นชื่อฟิลด์ว่างและค่าว่าง
// Serialize the specified form into a query string.
//
// Returns a blank string if +form+ is not actually a form element.
function $serialize(form, evt) {
if(typeof(form) !== 'object' && form.nodeName !== "FORM")
return '';
var evt = evt || window.event || { target: null };
evt.target = evt.target || evt.srcElement || null;
var field, query = '';
// Transform a form field into a query-string-friendly
// serialized form.
//
// [NOTE]: Replaces blank spaces from its standard '%20' representation
// into the non-standard (though widely used) '+'.
var encode = function(field, name) {
if (field.disabled) return '';
return '&' + (name || field.name) + '=' +
encodeURIComponent(field.value).replace(/%20/g,'+');
}
// Fields without names can't be serialized.
var hasName = function(el) {
return (el.name && el.name.length > 0)
}
// Ignore the usual suspects: file inputs, reset buttons,
// buttons that did not submit the form and unchecked
// radio buttons and checkboxes.
var ignorableField = function(el, evt) {
return ((el.type == 'file' || el.type == 'reset')
|| ((el.type == 'submit' || el.type == 'button') && evt.target != el)
|| ((el.type == 'checkbox' || el.type == 'radio') && !el.checked))
}
var parseMultiSelect = function(field) {
var q = '';
for (var j=field.options.length-1; j>=0; j--) {
if (field.options[j].selected) {
q += encode(field.options[j], field.name);
}
}
return q;
};
for(i = form.elements.length - 1; i >= 0; i--) {
field = form.elements[i];
if (!hasName(field) || field.value == '' || ignorableField(field, evt))
continue;
query += (field.type == 'select-multiple') ? parseMultiSelect(field)
: encode(field);
}
return (query.length == 0) ? '' : query.substr(1);
}
evt = evt || window.event || { target: null };
(ตามที่การแก้ไขเสร็จสิ้น) จุดที่อยู่เบื้องหลังคือการส่งผ่านเหตุการณ์ที่ทำให้เกิดการทำให้เป็นอนุกรมหากมีเช่นแบบฟอร์ม "ส่ง" เหตุการณ์หรือ "คลิก" ของปุ่ม หากแบบฟอร์มมีปุ่มหลายปุ่มสำหรับการส่งคุณต้องการพิจารณาเฉพาะค่าของปุ่มที่ทำให้เกิดเหตุการณ์และไม่สนใจปุ่มอื่น ๆ ฉันได้แฮ็กตัวอย่างพื้นฐานของพฤติกรรมนี้ในdump.bedmonds.net/serialize-js
ซึ่งสามารถทำได้โดยใช้ฟังก์ชันง่ายๆดังนี้
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);
<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>
// supports IE8 and IE9
function serialize(form) {
var inputs = form.elements;
var array = [];
for(i=0; i < inputs.length; i++) {
var inputNameValue = inputs[i].name + '=' + inputs[i].value;
array.push(inputNameValue);
}
return array.join('&');
}
//using the serialize function written above
var form = document.getElementById("form");//get the id of your form. i am assuming the id to be named form.
var form_data = serialize(form);
var xhr = new XMLHttpRequest();
xhr.send(form_data);
//does not work with IE8 AND IE9
var form = document.querySelector('form');
var data = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.send(data);
ฉันได้รับรายการ () วิธีการของ formData จากคำตอบ @moison และจากMDNมีการกล่าวว่า:
FormData.entries () วิธีการส่งคืนตัววนซ้ำที่อนุญาตให้ผ่านคู่คีย์ / ค่าทั้งหมดที่มีอยู่ในวัตถุนี้ คีย์ของแต่ละคู่คือวัตถุ USVString ค่า USVString หรือ Blob
แต่ปัญหาเดียวคือเบราว์เซอร์มือถือ (ไม่รองรับ Android และ Safari) และ IE และเดสก์ท็อป Safari ด้วย
แต่โดยพื้นฐานแล้วนี่คือแนวทางของฉัน:
let theForm = document.getElementById("contact");
theForm.onsubmit = function(event) {
event.preventDefault();
let rawData = new FormData(theForm);
let data = {};
for(let pair of rawData.entries()) {
data[pair[0]] = pair[1];
}
let contactData = JSON.stringify(data);
console.warn(contactData);
//here you can send a post request with content-type :'application.json'
};
รหัสสามารถพบได้ที่นี่
การใช้ฟังก์ชันลด JavaScript ควรใช้เคล็ดลับสำหรับเบราว์เซอร์ทั้งหมดรวมถึง IE9>:
Array.prototype.slice.call(form.elements) // convert form elements to array
.reduce(function(acc,cur){ // reduce
var o = {type : cur.type, name : cur.name, value : cur.value}; // get needed keys
if(['checkbox','radio'].indexOf(cur.type) !==-1){
o.checked = cur.checked;
} else if(cur.type === 'select-multiple'){
o.value=[];
for(i=0;i<cur.length;i++){
o.value.push({
value : cur.options[i].value,
selected : cur.options[i].selected
});
}
}
acc.push(o);
return acc;
},[]);
ร้องตัวอย่างสด
ปรับปรุงตามคำตอบของ David Lemon
สิ่งนี้จะแปลงข้อมูลฟอร์มเป็น JSON และช่วยให้คุณตั้งค่าฟอร์มจากออบเจ็กต์ข้อมูล
const main = () => {
const form = document.forms['info'];
const data = {
"user_name" : "John",
"user_email" : "john@jonhson.com",
"user_created" : "2020-03-24",
"user_age" : 42,
"user_subscribed" : true,
"user_interests" : "sports",
"user_message" : "Hello My Friend"
};
populateForm(form, data);
updateJsonView(form);
form.addEventListener('change', (e) => updateJsonView(form));
}
const getFieldValue = (field, opts) => {
let type = field.getAttribute('type');
if (type) {
switch (type) {
case 'checkbox':
return field.checked;
case 'number':
return field.value.includes('.')
? parseFloat(field.value)
: parseInt(field.value, 10);
}
}
if (opts && opts[field.name] && opts[field.name].type) {
switch (opts[field.name].type) {
case 'int':
return parseInt(field.value, 10);
case 'float':
return parseFloat(field.value);
}
}
return field.value;
}
const setFieldValue = (field, value) => {
let type = field.getAttribute('type');
if (type) {
switch (type) {
case 'checkbox':
field.checked = value;
break;
default:
field.value = value;
break;
}
} else {
field.value = value;
}
}
const extractFormData = (form, opts) => {
return Array.from(form.elements).reduce((data, element) => {
return Object.assign(data, { [element.name] : getFieldValue(element, opts) });
}, {});
};
const populateForm = (form, data) => {
return Array.from(form.elements).forEach((element) => {
setFieldValue(element, data[element.name]);
});
};
const updateJsonView = (form) => {
let fieldOptions = {};
let formData = extractFormData(form, fieldOptions);
let serializedData = JSON.stringify(formData, null, 2);
document.querySelector('.json-view').textContent = serializedData;
};
main();
.form-field {
margin-bottom: 0.5em;
}
.form-field label {
display: inline-block;
font-weight: bold;
width: 7em;
vertical-align: top;
}
.json-view {
position: absolute;
top: 0.667em;
right: 0.667em;
border: thin solid grey;
padding: 0.5em;
white-space: pre;
font-family: monospace;
overflow: scroll-y;
max-height: 100%;
}
<form name="info" action="/my-handling-form-page" method="post">
<div class="form-field">
<label for="name">Name:</label>
<input type="text" id="name" name="user_name">
</div>
<div class="form-field">
<label for="mail">E-mail:</label>
<input type="email" id="mail" name="user_email">
</div>
<div class="form-field">
<label for="created">Date of Birth:</label>
<input type="date" id="created" name="user_created">
</div>
<div class="form-field">
<label for="age">Age:</label>
<input type="number" id="age" name="user_age">
</div>
<div class="form-field">
<label for="subscribe">Subscribe:</label>
<input type="checkbox" id="subscribe" name="user_subscribed">
</div>
<div class="form-field">
<label for="interests">Interest:</label>
<select required="" id="interests" name="user_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 class="form-field">
<label for="msg">Message:</label>
<textarea id="msg" name="user_message"></textarea>
</div>
</form>
<div class="json-view"></div>
นี่คือแนวทาง JavaScript ที่แท้จริง:
var form = document.querySelector('form');
var data = new FormData(form);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
};
xhttp.open("POST", "<YOUR-URL>", true);
xhttp.send(data);
}
ฉันหวังว่านี่จะได้ผล
var serializeForm = (formElement) => {
const formData = {};
const inputs = formElement.elements;
for (let i = 0; i < inputs.length; i++) {
if(inputs[i].name!=="")
formData[inputs[i].name] = inputs[i].value;
}
return formData;
}
document.serializeForm = function (selector) {
var dictionary = {};
var form = document.querySelector(selector);
var formdata = new FormData(form);
var done = false;
var iterator = formdata.entries();
do {
var prop = iterator.next();
if (prop.done && !prop.value) {
done = true;
}
else {
dictionary[prop.value[0]] = prop.value[1];
}
} while (!done);
return dictionary;
}
สำหรับวัตถุประสงค์ในการดีบักสิ่งนี้อาจช่วยคุณได้:
function print_form_data(form) {
const form_data = new FormData(form);
for (const item of form_data.entries()) {
console.log(item);
}
return false;
}
ฉันอาจจะบ้า แต่ฉันพบคำตอบเหล่านี้ป่อง นี่คือทางออกของฉัน
function serialiseForm(form) {
var input = form.getElementsByTagName("input");
var formData = {};
for (var i = 0; i < input.length; i++) {
formData[input[i].name] = input[i].value;
}
return formData = JSON.stringify(formData);
}
select
และอื่น ๆ