问题描述
我尝试创建一个具有丰富功能的jQuery的自定义小部件,因此我需要许多标准事件的自定义处理程序,例如DBLCLICK,CLISC,COPIT,FOCUS,BLUR等.
我可以应用两种策略之一:
-
使用$(document).on('click', '.widget-name .element-class', handle_click);
一旦全球handle_click为处理程序函数 -
使用$(widget-element).find('.element-class').on('click', handle_click)
在创建每个小部件实例 期间
-
绑定到这样的封闭元素:
$(this.element)._ on('click',function(event){
var $ this = $(this);
如果($ this.is('.元素级')){handle_click(this,event);}
否则if($ this.is(...)){...}
...
});
哪种方法是更好的设计?
我知道"这取决于",所以让我添加一些约束:
a.小部件通常由〜100个DOM元素组成,其中包含不同的事件.
b.小部件通常不会被破坏并再次创建,有时只会隐藏.
C.通常将加载小部件的1-3个实例.
d.将按用户请求动态添加元素,但同时仅<10
e.在小部件内启用了拖动-N-Drop,可能涉及同时重新定位约20元素.
F.小部件本身通常不可拖动.
由于定义了许多单独的事件处理程序吗?(是的,这可能取决于我知道的浏览器实现,因此对方法2是否有实质性的性能(或实质性记忆)罚款.)
推荐答案
使用第一个形式是一次实现事件处理程序的简便方法,但它具有额外的开销.实际上,每次点击文档都会调用处理程序,然后jQuery必须检查目标是否与选择器匹配.使用第二个表单,浏览器仅在单击其绑定到的特定元素时调用处理程序.
第一个形式也可以以微妙的方式失败.如果有封闭的元素具有自己的点击处理程序,并且它们使用event.stopPropagation(),这将防止事件冒泡到document,因此永远不会调用.on()处理程序.
常规应用程序开发人员可以通过将事件与最深层嵌套的元素结合来减轻这两个问题,这些元素包围了他们想要授权的动态元素.但是,小部件开发人员对上下文没有那么多知识,因此它可能必须使用代码中的宽document范围.如果您可以实现第二个表单,则在将元素添加到DOM时添加处理程序,这可能会更好.
您可能可以轻松地做到这一点的一种方法是使用jQuery的.clone()方法.它需要一个可选的论点,指示是否应复制处理程序.因此,使用处理程序绑定创建一个原型元素,然后克隆它,新元素也将具有处理程序.
其他推荐答案
好吧,如果您有多个事件,我建议这样做:
$(document).on({ click: clickFn, dblclick: dblFn, mouseover: mouseFn, ... }, '.widget-name .element-class');
但是要回答您的问题:
- 这一切都取决于您是否要事件委托,还是将事件附加 直接 上的对象
- 我不确定
问题描述
I try to create a custom widget with jquery with rich functionality, therefore I need custom handlers for many standard events such as dblclick, click, focus, blur etc.
I can apply one of two strategies:
Use $(document).on('click', '.widget-name .element-class', handle_click);
once globally where handle_click is the handler functionUse $(widget-element).find('.element-class').on('click', handle_click)
during the creation of each widget instanceBind to the enclosing element like this:
$(this.element)._on('click', function(event){
var $this = $(this);
if($this.is('.element-class')){ handle_click(this, event);}
else if($this.is(...)){...}
...
});
Which approach is better design?
I know "it depends" in general, so let me add some constraints:
a. the widget will typically consist of ~100 DOM elements with different events handled specially.
b. the widget will typically not be destroyed and created again, only hid sometimes.
c. typically 1-3 instances of the widget will be loaded.
d. elements will be added dynamically upon user request but only <10 at the same time
e. drag-n-drop is enabled within the widget that may involve repositioning ~20s of DOM elements at the same time.
f. the widget itself is typically not draggable.
Is there a substantial performance (or substantial memory) penalty on approach 2 due to defining many separate event handlers? (Yes, that could depend on browser implementations I know.)
推荐答案
Using the first form is an easy way to implement the event handler once, but it has extra overhead. The handler is actually invoked for every click on the document, jQuery then has to check whether the target matches the selector; with the second form, the browser only invokes the handler when you click on the specific elements that it's bound to.
The first form can also fail in a subtle way. If there are enclosing elements that have their own click handlers, and they use event.stopPropagation(), this will prevent the event from bubbling up to the document, so the .on() handler will never be invoked.
Regular application developers can mitigate both problems by binding the event to the most deeply nested elements that enclose the dynamic elements they want to delegate to. But a widget developer doesn't have as much knowledge of the context, so it may have to use the wide document scope as in your code. If you can implement the second form, adding the handlers as you add elements to the DOM, that's likely to be better.
One way you may be able to do this easily is by using jQuery's .clone() method. It takes an optional argument indicating whether handlers should be copied. So create a prototype element with the handler bound, then clone it and the new element will also have the handler.
其他推荐答案
Well if you have multiple events I would suggest doing this:
$(document).on({ click: clickFn, dblclick: dblFn, mouseover: mouseFn, ... }, '.widget-name .element-class');
But to answer your questions:
- It all depends on if you want event delegation or if you attaching the event directly to an object on the page
- I am not sure