Ember 2.18特定场景下如何正确阻止事件冒泡?
嘿,这个问题我熟!在Ember 2.18里确实有两种可行的方式来阻止事件冒泡,刚好能解决你遇到的容器点击展开、内部按钮点击却触发容器事件的冲突问题,我给你详细拆解下:
1. 官方推荐方案:用动作的bubbles选项
这是最贴合Ember设计理念的方式,直接在模板的{{action}}助手上加bubbles=false参数,就能精准阻止动作向上冒泡到父元素,完全不用碰原生DOM事件:
模板代码示例:
{{! 父容器,点击触发展开动作 }} <div {{action 'expandContainer'}} class="expandable-container"> {{! 内部关闭按钮,动作设置为不冒泡 }} <button {{action 'closeContainer' bubbles=false}}>关闭容器</button> </div>
然后在你的组件(或控制器)里定义对应的动作逻辑:
actions: { expandContainer() { // 这里写展开容器的代码,比如切换isExpanded属性 this.set('isExpanded', true); }, closeContainer() { // 关闭容器的逻辑 this.set('isExpanded', false); } }
这种方式的好处是代码简洁、语义明确,而且在后续Ember版本中一直被官方支持,是绝对的最佳实践。
2. 能生效但不推荐的方案:手动调用stopPropagation
另一种方式是在动作函数里获取原生DOM事件对象,然后调用event.stopPropagation()来阻止冒泡:
模板代码:
<div {{action 'expandContainer'}} class="expandable-container"> <button {{action 'closeContainer' on='click'}}>关闭容器</button> </div>
组件中的动作实现:
actions: { expandContainer() { this.set('isExpanded', true); }, closeContainer(event) { // 手动阻止事件冒泡到父容器 event.stopPropagation(); // 执行关闭逻辑 this.set('isExpanded', false); } }
这种方法虽然能解决问题,但它依赖原生DOM事件,违背了Ember“尽量封装DOM操作”的设计思路,而且在最新版Ember文档里已经不再重点提及这种方式,相当于被官方逐渐弃用,所以不建议你用这个方案。
总结一下,直接用bubbles=false就对了,简单靠谱还符合规范!
内容的提问来源于stack exchange,提问作者Nil




