dojo.dijit.Button 触发 onclick 事件两次

Posted

技术标签:

【中文标题】dojo.dijit.Button 触发 onclick 事件两次【英文标题】:dojo.dijit.Button fires onclick event twice 【发布时间】:2011-10-21 16:53:57 【问题描述】:

我正在自定义小部件内实例化一个 dijit 按钮。那一点都很好。在小部件代码中,我绑定了一个 onclick 事件处理程序,但是当我单击按钮时,事件会触发两次。第二个问题是它还将点击事件绑定到页面中与小部件无关的其他按钮。下面是我所拥有的简化版本。谁能告诉我为什么这样做。我花了过去几个小时试图修复它。

代码如下,但你也可以在这里看到它

这是实例化自定义小部件的 html 页面 https://github.com/screenm0nkey/dojo/blob/master/widgets/destroy-widget.html

这是自定义小部件 https://github.com/screenm0nkey/dojo/blob/master/js/tag/widgets/DestroyWidget/Widget.js

这是包含嵌套小部件的模板 https://github.com/screenm0nkey/dojo/blob/master/js/tag/widgets/DestroyWidget/templates/template.html

这是小部件模板中的 html;

<div style="border: solid 1px pink">
<h3>$name</h3>

<div dojoType="dijit.form.Button" data-dojo-attach-point="removeBtn" class="removeBtn">
  click me.
</div>

这是绑定处理程序的小部件内的 JavaScript;

define('tag/Widget', ['dojo', 'dojo/parser', 'dijit/_Widget', 'dijit/_TemplatedMixin'],

function(d, parser) 

return d.declare('tag.Widget', [dijit._Widget, dijit._TemplatedMixin], 

templateString : d.cache("tag", "/templates/template.html"),
widgetsInTemplate : true,
name : 'no name',
button : 'no button',

postCreate : function() 
  parser.parse(this.domNode);
  this.placeAt(d.byId('authorContainer'));
,

startup : function() 
  dijit.registry.forEach(dojo.hitch(this, function(w) 
    if (w.class === 'removeBtn') 
      this.button = w;
      return;
    
  ))

  this.button.connect('onclick', function(evt) 
    console.log(evt.target);
  );
,

); );

这是控制台输出;

<input type="button" value="" class="dijitOffScreen" tabindex="-1" role="presentation" data-dojo-attach-point="valueNode">
<span class="dijitReset dijitInline dijitButtonText" id="dijit_form_Button_0_label" data-dojo-attach-point="containerNode">click me.</span>

【问题讨论】:

添加了fiddle 【参考方案1】:

我不知道您遇到问题的确切原因,但我认为如果您使用更“Dojo 风格”的做事方式而不是当前使用类进行导航的“JQuery 风格”,您可能会避免它:

    尝试使用新的 data-dojo 属性而不是旧的 dojoType 样式:

    <div data-dojo-type="dijit.form.Button" class="remove">
    

    使用显式附加点来引用内部小部件:

    <div data-dojo-type="dijit.form.Button"
         data-dojo-attach-point="removeBtn"            
         class="remove">
        Click me
    </div>
    

    附加点将设置主小部件的属性。您可以通过它访问按钮

    dojo.connect(this.removeBtn, ...
    

    使用 onClick 代替 onclick 连接到小部件

    dojo.connect(this.removeBtn, 'onClick', function() ... );
    

【讨论】:

您好missingno,这不起作用。这是我在阅读 dojo 文档后首先尝试的。附加点仅可用作为按钮创建的对象的属性,但不能用作自定义小部件内的属性,这是我绑定功能的地方。所以在自定义小部件的 postCreate 方法中引用 this.removeBtn 会导致未定义的值。 嗨missingno,只是一个更新,但我尝试通过dijit.registry.forEach运行,获取按钮对象并使用它的connect方法绑定点击事件,它仍然做同样的事情。 @screenm0nkey:只要您的自定义小部件的按钮是模板化的,并且在模板内声明了按钮,attachPoint 应该可以正常工作。您应该尝试在 JSFiddle 上发布一个最小的工作示例,因为我们无法真正猜出您实际上犯了什么小错误。 有几个原因我没有摆弄它,但主要是因为我正在使用带有 _TemplatedMixin 的 dojo 1.7,其次是因为我认为这将是一个快速的答案。我将切换回 1.6,看看它是否做同样的事情,然后我会更好地了解是我还是道场。我还将在我的 github 帐户上发布指向文件的链接,以便您可以在那里看到它们。感谢您迄今为止的帮助。 模板 changed from 1.6 to 1.7 内的小部件。您需要添加一个新的 _WidgetsInTemplateMixin mixin 而不是使用 widgetsInTemplate 标志【参考方案2】:

dijit.form.Button 在其内部按钮输入上调度第二次点击事件。检查source。我不能告诉你为什么。

我建议连接到 widget's onClick event 而不是 DOM 事件。 missingno 的回答描述了设置。

【讨论】:

嗨 hurraymapled,感谢您的回复。遗憾的是,missingno answer 不起作用(请参阅下面的帖子)。至于将内联 javascript 添加到 html 模板中,这是不好的做法,因此我试图将所有 JS 保留在小部件中。我必须有一种简单的方法来引用从自定义小部件内部创建的按钮对象。我只是还不知道怎么做。我可以使用 dijit 注册表破解它,但 dojo 是为嵌套小部件而构建的,因此必须有一个简单的方法。【参考方案3】:

使用data-dojo-attach-event 自动为您连接处理程序。

在您的 javascript 中,添加一个您希望在单击按钮时调用的函数:

// somewhere in your dojo.declare...
remove: function () 
    // do your remove stuff here
,

然后在你的模板中,你会有一些这样的标记:

<div data-dojo-type="dijit.form.Button" data-dojo-attach-event="onClick:remove">
    Remove
</div>

该标记的意思是您希望将按钮的onClick 连接到拥有该模板的小部件的remove 函数。

作为奖励,此连接的管理已为您处理,因此当您的小部件被销毁时,您无需执行任何操作即可正确断开连接。 如果您要自己执行dojo.connect,那么您应该存储对dojo.connect 返回的句柄的引用,并在您的小部件被销毁时执行dojo.disconnect

【讨论】:

感谢 neonstalwart。由于某种原因,这根本不起作用。尝试了各种测试,但没有触发它。 对我也不起作用,但听起来很合理!我最终停止了事件传播:***.com/a/32176663/2586761【参考方案4】:

我在维护工作中遇到了这个问题..

我最终停止了事件传播:

clickFunction: function(e) 
    // business logic here...
    e.stopPropagation();
    window.event.cancelBubble = true; // IE
,

我相信我的模板(用翡翠,对不起)是正确的:

button(data-dojo-type="dijit.form.ToggleButton",
       data-dojo-attach-event="onClick: clickFunction") Text

为我工作!

【讨论】:

以上是关于dojo.dijit.Button 触发 onclick 事件两次的主要内容,如果未能解决你的问题,请参考以下文章

iScroll中事件点击触发两次解决方案

用事件冒泡实现在div内点击,不触发事件,当在div外点击时才触发事件

如何调用onclick以获得更多href,而不仅仅是触发最后一个-嵌入式javascript模板

访问表单 VBA ComboBox 点击事件

谨记谨记

html,点击链接后停顿几秒再进入超链接,用啥函数 因为css按钮有个动画,想让他显示完了再进入