【问题标题】:Preventing form submission with Dojo使用 Dojo 防止表单提交
【发布时间】:2010-10-02 08:42:40
【问题描述】:

我有一个带有 jsId="saveParamButtonWidget" 的 Dojo SubmitButton。我通过放置覆盖了它的 onClick 方法:

saveParamButtonWidget.onClick = editParam

我这样定义了 editParam() 函数:

function editParam(eventObj) {
    dojo.stopEvent(eventObj);
    // ...
}

dojo.stopEvent() 应该停止事件冒泡和默认处理。但是,浏览器无论如何都会提交表单。我还尝试了以下方法:

function editParam(eventObj) {
    eventObj.stopPropagation();
    eventObj.preventDefault();
    // ...
}

同样的事情。我设法阻止表单提交的唯一方法是从事件处理程序返回“false”:

function editParam(eventObj) {
    // ...
    return false;
}

谁能告诉我为什么前两种方法不起作用?谢谢。

【问题讨论】:

  • 请提供更多信息:您使用了什么类型的小部件(全名),dojo 不知道“SubmitButton”,我想这是一个 dijit.form.Button,类型为“提交”。一个代码 sn-p 会有很大帮助
  • 对不起,我使用的是 Zend Framework 的 Dojo 提交元素,称为 SubmitButton。但你是对的,它是一个 dijit.form.Button,类型为“submit”。

标签: javascript dojo


【解决方案1】:

好的,经过一番挖掘,我相信我可以肯定地回答你的问题。

dojo.stopEvent() 不起作用,而return false 起作用的原因完全是由于dijit.form.Button 的编码方式。如果你有兴趣,是时候进行一次实地考察了。戴上安全帽。

当点击dijit.form.Button 时...

  1. 按钮的_onButtonClick 方法被调用。 (这与模板中的特殊 ondijitclick 事件相关联,该事件不仅捕获鼠标单击,还捕获某些按键,用于 a11y 目的。)
  2. _onButtonClick 方法首先调用_onClick 方法,假设按钮没有被禁用(在这种情况下不是这样),调用并返回onClick 的结果方法。这特别有趣,因为它是您要覆盖的方法!
  3. 回到_onButtonClick,如果_onClick返回准确false(例如,如果您的onClick处理程序返回false),_onButtonClick立即退出。 这就是为什么返回 false 会使您的代码按预期工作。但是如果它在那里退出会发生什么?让我们更进一步……
  4. 接下来,_onButtonClick 检查此按钮是否不是实际 HTML 表单的后代,但 具有 _onSubmit 方法的小部件的后代(鸭-打字)。我假设在你的情况下它 在一个 real 表单中(dijit.form.Form 计数),所以我们将跳过这个。 (我的印象是此代码路径实际上不会最终提交,而您的显然会提交。)
  5. 检查最后一个条件:如果按钮定义了valueNode(确实如此),则调用该节点的click 方法。不幸的是,这会在表单下的不可见 input type="submit" 节点上产生一个全新的事件对象,因此您试图告诉原始事件的任何内容都被渲染为无关紧要,表单继续提交! 这就是 dojo.stopEvent 不起作用的原因 - dijit.form.Button 中的这段代码完全不理会它。

我把它作为一个有限的概念证明(一定要打开 firebug/etc. 来获取日志):http://jsfiddle.net/Bf5H8/

也许这应该被记录为错误,但我想最初的想法可能是支持众所周知的return false 机制就足够了。

话虽如此,覆盖表单的 onSubmit 很可能比覆盖按钮的 onClick 更符合您的兴趣(正如 S.Jones 所建议的那样),但至少这应该解决这个谜。

【讨论】:

  • 非常感谢您的努力,肯。
  • 我与 Doug 确认了这一点,这是设计使然。正如您的分析所示,支持 stopEvent() 会很麻烦,因为有两个事件对象。另一个需要返回 false 的示例是表单中的 onSubmit 方法。在这种情况下,甚至没有一个事件对象可以调用 stopEvent()。
【解决方案2】:

有趣的问题。 +1

我相信您必须使用 dojo.connect 将您的函数连接到一个 DOM 事件,才能通过事件对象访问这些方法。

见:The Event Object (DojoTollkit.org Reference Guide)

事件对象

当你将函数连接到 DOM 时 与 dojo.connect 的事件, Dojo 将您的函数传递给标准化 事件对象。这意味着, 无论客户端的浏览器如何, 你可以指望一套标准 关于事件和集合的属性 操作事件的方法。

假设你的函数已经 由 dojo.connect 调用并接受 名为 event 的参数,例如:

dojo.connect(dojo.byId("node"), "onclick", function(event){
    // the var 'event' is available, and is the normalized object 
});

...

Dojo 使用事件对象规范化以下方法:

  • event.preventDefault — 阻止事件的默认行为(例如,链接加载新页面)
  • event.stopPropagation — 防止事件触发父节点的事件

此外,dojo.stopEvent(event) 将阻止任何默认行为 的任何传播(冒泡) 事件。


也就是说,在表单中放置一个类似下面的函数以在提交之前执行一些逻辑,是一种相当干净、易于理解和可维护的方法。

<script type="dojo/method" event="onSubmit">
    if (!this.validate()) { // or whatever else you'd like to evaluate
        // insert calls here...
        return false;
    }
    return true;
<script>

干杯。

【讨论】:

  • 从技术上讲,直接设置 onClick 方法不会发生任何不好的事情,因为它只是 dijit._Widget 中的一个存根,无论如何都要被钩住。事实上,使用 dojo.connect(或者更好的是 yourwidget.connect)实际上会更糟糕,因为那样return false 也不起作用。
【解决方案3】:

我在使用 dojo.stopEvent 时遇到了同样的问题

这个问题解决了这样的表单提交问题 - 这里是一个用于通过dojo连接的简单表单:

this.formId = dojo.byId("formId");
dojo.connect(this.formId, 'onsubmit', function(evt) {
    var val_main = validate_this_form(0);
       if(val_main == false)
           dojo.stopEvent(evt);
});

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    相关资源
    最近更新 更多