EmberJS - 如何不与组件中的动作和事件发生冲突
EmberJS - How not to conflict with actions and events in components
我认为组件中的模板操作和事件之间存在问题。
据我了解,所有操作点击都将首先执行并冒泡。
最后,组件中的事件也会被执行。
好像有两个并行的栈一个接一个执行。
如果组件模板中有这样的内容:
Hello <button onclick={{action 'clickMe'}}>Click me</button>
在相应的 javascript 文件中:
click: function() {
alert('second message');
}
您不确定是否会显示第二条消息。如果在动作堆栈中调用了event.stopPropagation()(在动作'clickMe'中没有必要),则不会显示第二条消息。
这是一个小游戏:https://ember-twiddle.com/c9a014a0c19851596d5e1184c9967cbc
有没有绕过这个问题的解决方案?
当你说 <button onclick={{action 'clickMe'}}>Click me</button>
- 它与 ember 无关,它只是为点击事件注册的正常功能。
当你说,<button {{action 'clickMe'}}>Click me</button>
这里Ember会接管(我不太确定我在说什么,但一般来说事件处理将由Ember处理)。
twiddle1 - Ember 正在处理所有事件处理(即,<div {{action 'test'}}>
然后你可以期望,事件从子组件传播
输出:
action click from my-child
click from my-child
action click from my-parent
click event from my-parent
整洁,这是预期的行为。即使您调用 event.stopPropagation 父组件,它也没有做任何事情。
twiddle 2 - 浏览器正在处理事件,即 <div onclick={{action 'test'}}>
输出:
action click from my-child
action click from my-parent
click from my-child
click event from my-parent
这里可以先将它的触发动作click从child传到parent,再调用相应组件的click handler。在这种情况下,如果您在父操作点击处理程序中调用 event.stopPropagation()
,那么 ember 将没有机会调用 parent/child 组件的点击处理程序。
这就是您遇到的问题,要解决您可以从 <div onclick={{action 'clickMe'}}>
移动到 <div {{action 'clickMe'}}>
。
我反对@kumkanillam 在他的回答中提出的建议:“要解决,您可以从 <div onclick={{action 'clickMe'}}>
移动到 <div {{action 'clickMe'}}>
。”
第一个(您在问题中使用的原始那个)是 ember 的 closure action
在起作用 :) 它更强大;这样你就可以 return 从父组件到子组件的值;因为它实际上是一个函数,其中 this
上下文由下面的 ember
正确设置,您可以急切地检测未处理的操作。另一方面,@kumkanillam 建议的通常命名为 "action in element space"。 Ember.
的低级别 DOM 事件处理
请看下面精彩的article解释为什么closure actions
摇滚!关于你的问题;我建议尽可能多地使用 closure actions
并通过将相关代码部分移动到操作处理来避免 DOM 事件操作处理,正如@DanielKmak 在他的评论中已经提到的那样。我个人更喜欢尽可能多地关闭操作,并且只在不可避免时依赖 DOM 事件处理程序(例如 box-content
中的 click
和你的 twiddle 中的 my-component
)。
我认为组件中的模板操作和事件之间存在问题。
据我了解,所有操作点击都将首先执行并冒泡。 最后,组件中的事件也会被执行。 好像有两个并行的栈一个接一个执行。
如果组件模板中有这样的内容:
Hello <button onclick={{action 'clickMe'}}>Click me</button>
在相应的 javascript 文件中:
click: function() {
alert('second message');
}
您不确定是否会显示第二条消息。如果在动作堆栈中调用了event.stopPropagation()(在动作'clickMe'中没有必要),则不会显示第二条消息。
这是一个小游戏:https://ember-twiddle.com/c9a014a0c19851596d5e1184c9967cbc
有没有绕过这个问题的解决方案?
当你说 <button onclick={{action 'clickMe'}}>Click me</button>
- 它与 ember 无关,它只是为点击事件注册的正常功能。
当你说,<button {{action 'clickMe'}}>Click me</button>
这里Ember会接管(我不太确定我在说什么,但一般来说事件处理将由Ember处理)。
twiddle1 - Ember 正在处理所有事件处理(即,<div {{action 'test'}}>
然后你可以期望,事件从子组件传播
输出:
action click from my-child
click from my-child
action click from my-parent
click event from my-parent
整洁,这是预期的行为。即使您调用 event.stopPropagation 父组件,它也没有做任何事情。
twiddle 2 - 浏览器正在处理事件,即 <div onclick={{action 'test'}}>
输出:
action click from my-child
action click from my-parent
click from my-child
click event from my-parent
这里可以先将它的触发动作click从child传到parent,再调用相应组件的click handler。在这种情况下,如果您在父操作点击处理程序中调用 event.stopPropagation()
,那么 ember 将没有机会调用 parent/child 组件的点击处理程序。
这就是您遇到的问题,要解决您可以从 <div onclick={{action 'clickMe'}}>
移动到 <div {{action 'clickMe'}}>
。
我反对@kumkanillam 在他的回答中提出的建议:“要解决,您可以从 <div onclick={{action 'clickMe'}}>
移动到 <div {{action 'clickMe'}}>
。”
第一个(您在问题中使用的原始那个)是 ember 的 closure action
在起作用 :) 它更强大;这样你就可以 return 从父组件到子组件的值;因为它实际上是一个函数,其中 this
上下文由下面的 ember
正确设置,您可以急切地检测未处理的操作。另一方面,@kumkanillam 建议的通常命名为 "action in element space"。 Ember.
请看下面精彩的article解释为什么closure actions
摇滚!关于你的问题;我建议尽可能多地使用 closure actions
并通过将相关代码部分移动到操作处理来避免 DOM 事件操作处理,正如@DanielKmak 在他的评论中已经提到的那样。我个人更喜欢尽可能多地关闭操作,并且只在不可避免时依赖 DOM 事件处理程序(例如 box-content
中的 click
和你的 twiddle 中的 my-component
)。