为啥 JavaScript 拦截“在野外”(在网页上)工作的 formData 不能在小提琴中工作?

Posted

技术标签:

【中文标题】为啥 JavaScript 拦截“在野外”(在网页上)工作的 formData 不能在小提琴中工作?【英文标题】:Why does JavaScript to intercept formData that works 'in the wild' (on a web page) not work in a fiddle?为什么 JavaScript 拦截“在野外”(在网页上)工作的 formData 不能在小提琴中工作? 【发布时间】:2019-11-05 09:18:47 【问题描述】:

我在提交事件上使用回调函数来检索 formData。它在我的web site 上的这个test page 上正常工作。我试图建立一个小提琴来解决另一个问题。我发现相同的代码在小提琴中不起作用。它返回一个带有array.length == 0 的formData,而不是正确的formData。

代码使用 jQuery 作为 document.ready 函数。 jQuery 已正确加载。

JavaScript:

01:    /*  doc.ready w/ traditional callback fn for event listener  */
02:
03:    $(document).ready( function() 
04:      init();
05:
06:    );  // end doc.ready
07:
08:    function init() 
09:      document.addEventListener("submit", processFormData);
10:      // end def fn init
11:
12:    functon processFormData(event) 
13:      var formData = new FormData();
14:      event.preventDefault();
15:      formData = $( 'form' ).serializeArray();
16:
17:                console.log('formData : ', formData);
18:
19.      //  end def fn processFormDat;

在实时表单中输入数据后,formData 返回一个数组,在相关部分,是这样的:

3: Object name: "select-yui_3_nnn ... nnn-field", value: "unsure"
4: Object name: "select-yui_3_nnn ... nnn-field", value: "A"
5: Object name: "select-yui_3_nnn ... nnn-field", value: "B"
6: Object name: "select-yui_3_nnn ... nnn-field", value: "A"
7: Object name: "select-yui_3_nnn ... nnn-field", value: "unsure"
8: Object name: "select-yui_3_nnn ... nnn-field", value: "C"
length: 9

formData.name 'yui' 属性不是常量。它们在每次页面加载时动态生成。它们不能用于引用项目。)

在the fiddle,控制台是这样的:

formData : Array []

formData.length == 0.

那么,问题是为什么?

HTML: 我的网站是在 Squarespace 平台上使用它的“表单块”之一构建的。 html 非常复杂。我不会尝试在这里复制它。

小提琴中的 HTML 很简单。我在这里复制它,这样你就不必点击了。

01;  <form method="POST">
02:  <div>
03:    <label>First Name
04:      <input type="text" size="25">
05:    </label>
06:  </div>
07:  <div>
08:    <label>Last Name
09:      <input type="text" size="25">
10:    </label>
11:  </div>
12:  </form>

console.config(
  maxEntries: Infinity
);

/*  doc.ready w/ traditional callback fn for event listener  */

$(document).ready(function() 
  init();
); // end doc.ready

function init() 
  document.addEventListener("submit", processFormData);
 // end def fn init

function processFormData(event) 
  var formData = new FormData();
  event.preventDefault();
  formData = $('form').serializeArray();

  console.log('formData : ', formData);

 //  end def fn processFormData
.as-console-wrapper 
  max-height: 100% !important;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="testForm" method="post">
  <div>
    <label>First Name
    <input type="text" name="fname"  size="25">
  </label>
  </div>
  <div>
    <label>Last Name
    <input type="text" name="lname" size="25">
  </label>
  </div>
  <div>
    <label>email address
    <input type="email" name="email" size="25">
  </label>
  </div>
  <div>
    <label>08:30 Keynote Speaker
    <select name="select0830">
      <option value="">unsure</option>
      <option value="attend">attend</option>
      <option value="not attend">not attend</option>
    </select>
  </label>
    <label>09:00 Classes
    <select name="select0900">
      <option value="">unsure</option>
      <option value="class room A">room A</option>
      <option value="class room B">room B</option>
    </select>
    </label>
    <label>10:30 Classes
    <select name="select1030">
      <option value="">unsure</option>
      <option value="class room A">room A</option>
      <option value="class room B">room B</option>
    </select>
  </label>
  </div>
  <div>
    <input type="submit" value="submit form">
  </div>
</form>

【问题讨论】:

参见api.jquery.com/serializeArray:“.serializeArray() 方法使用标准 W3C 规则来成功控制以确定它应该包含哪些元素;特别是该元素不能被禁用并且 必须包含名称属性。” 另外,您需要在问题中包含minimal reproducible example。见How to Ask。最好的方法是使用内置的 sn-p 编辑器。您当前的问题包含不完整的代码和不必要的行号,并且缺少一些元素。 @Herohtar :感谢您指出堆栈片段。我在问题中添加了一个。感谢您提供有关 name 属性的信息。在 sn-p 中,我在表单字段中添加了名称。这解决了问题。它也解释了为什么 js 在我的测试页面上工作。我使用浏览器的元素检查器查看每个字段的名称属性/我应该考虑尝试在 serializeArray() 上查找文档。至于不完整的代码,我相信你错了。 19行js都在测试页面的js里面。我看不到任何缺失的元素。再次感谢,非常感谢! 我没有弄错不完整的代码,但我说的是 HTML,而不是 javascript——看看你的问题中仍然存在的原始 HTML 列表:有一个&lt;div&gt; 末尾的标签没有结束标签,它不包含任何提交按钮,&lt;form&gt; 也缺少它的结束标签。 @Herohtar 感谢您的坚持。我为草率的 HTML 道歉。再次感谢您之前的两个 cmets,当我与 Nick Parsons 下面的回答一起阅读它们时,给了我答案。我将他标记为已接受的答案,但也对您的两个 cmets 投了赞成票。 【参考方案1】:

您的问题在于您对方法的使用:

$('form').serializeArray();

.serializeArray() 将查看您给它的表单,并使用表单中每个表单控件的name 字段构建一个对象数组。正如您所说,name 字段是动态生成的,只有在生成它们时您才会得到结果。如果永远不会生成 name 属性,那么您将永远不会获得数据(因为它们永远不会在您的 sn-p 中生成,您将永远不会获得数据)。

因此,为了让.serializeArray 工作,您需要为表单输入提供name 属性。

查看工作示例here

另外请注意,不需要new FormData()。你正在用$('form').serializeArray();返回的数组覆盖这个数据

【讨论】:

非常感谢!在您的回答和@herchtar 的 cmets 之间,我理解。它解释了为什么代码在我网站的测试页面上有效。每个表单元素都有一个名称属性。它们的选择器名称确实是“yui”名称。但是 doc.ready 项目应该处理这个问题,不是吗?在显示表单时,这些标签都具有名称属性。 doc.ready 阻止 js 执行,直到所有 HTML 元素都到位。我不能 使用 js 中的 name 属性,但至少在我的情况下,我不需要。再次感谢您的解释。这是最有帮助的。 @alxfyv 是的,你是对的。名称属性应该动态添加到您的元素中,因此无需为您的站点添加名称属性。

以上是关于为啥 JavaScript 拦截“在野外”(在网页上)工作的 formData 不能在小提琴中工作?的主要内容,如果未能解决你的问题,请参考以下文章

markdown EmberJs应用程序在野外

当我的应用程序在野外崩溃时,如何提高调试数据的质量?

请问这是啥花!在野外发现的,问问花的名字。谢谢!

为啥webstorm 打开网页 崩溃

为啥没有更多的 Java 代码使用 PipedInputStream / PipedOutputStream?

第一个javascript程序 为啥点开网页没有弹窗