简体   繁体   中英

Event delegation and the global `event` object in Ember action

Today I've learned a bit about the event delegation in Ember. The whole thing is exactly what I'd like to use in my code. There is a small problem though. When I migrate from

<div ondragend={{action "dragEnd"}}></div>

to

<div {{action "dragEnd" on="dragEnd"}}></div>

then I can't get the event parameter in my action method anymore and the thing is that I need it to get access to event.clientX/Y . This answer mentiones that it's possible to simply remove the parameter event and use it "globally" like this

...
actions: {
  dragEnd() {
    event.blahblah...
  }
}

So, I've got some questions regarding this technique:

  1. Can anyone tell me how legal is it? It's not documented anywhere.
  2. Do I understand correctly that in the case I use the closured action ( <div ondragend={{action "dragEnd"}}></div> ) it won't use the event delegation, ie it will attach the event handler to that div and not the body like it does according to the doc if I use this pattern ( <div {{action "dragEnd" on="dragEnd"}}></div> )?

First why would you migrate to {{action "dragEnd" on="dragEnd"}} ? Thats the oldest style of ember actions and you shouldnt use them. Use ondragend={{action "dragEnd"}} or better {{on "dragEnd" this.dragEnd}} when using a new action decorated with @action . If you have your action in the actions hash use {{on "dragEnd" (action "dragEnd")}} .

and while window.event is a browser feature I woudlnt use it: Reference to MDN:

You should avoid using this property in new code

  1. is correct. basically:

    • the {{action modifier (used without = before the {{action ) will not attach any native event handlers, but waits for the event to bubble up to body where the event must already be registered (ember does this for a preset list of events) and then use a ember internal handling mechanism to trigger your action. This is basically from the old days, you should migrate away from it.
    • when you do eventname={{action you use the {{action helper . While it has the same name as the modifier it is not the same thing at all. The {{action helper just finds the action in the actions hash on your class, creates a bound action with maybe passed parameters and binds it to the correct this . Then this resulting action is assigned to the eventname property of the HTML DOM Element. This was a long time a very common way to do things, but never the officially preferred one. However its still a pretty good way to do things. The primary downside is that you cant add multiple actions to the same event. so onclick={{action "foo}} onclick={{action "bar}} on the same Element wont work.
    • the new {{on modifier is the new way to go with ember octane. It basically runs addEventListener . This allows to add multiple handlers as the {{action modifier does, but uses far less ember magic and directly adds the event to the DOM Element, not using any strange magic with custom event delegation. However it does not do any action lookup. So the second parameter directly needs to be a bound function that can be passed to addEventListener . For ember octane you would define the action directly on the class and add the @action decorator to it, which will basically create a bound function with the correct this context (it also adds the function to the actions hash to add compatibility with the {{action modifier and helper). For classic style actions you can use the {{action helper to look up the action and then pass it to the {{on modifier. Then you basically result in {{on "click" (action "myAction")}} .

So what to do:

  • try to avoid <button {{action "myAction" on="click"}}> whenever possible. migrate away from it.
  • when using classic style components/classes with Component.extend({ use <button onclick={{action "myAction}}> or <button {{on "click" (action "myAction")}}> .
  • when using native classes and/or glimmer components and you have your action decorated with the @action decorator use <button {{on "click" this.myAction}}> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM