如何使用Hammer.js 2.0中的stopPropagation()方法?

10

我有一个父div和一个子div。在子div上平移/拖动不应影响父div。这是一个类似的问题,但是已经是一年前的事情了,而且我正在使用带有jQuery包装器的更新版本的Hammer.js。

我的假设是我必须以某种方式停止事件传播(stopPropagation()),但我不确定如何使用它。

我已经创建了一个演示在JsFiddle上展示了我的问题。我也注释掉了我尝试过的东西。

$(".outer-box").hammer().bind("panright", function(event){
    // do stuff when panning
    // panning here should move both boxes
});
$(".outer-box").hammer().bind("panend", function(event){
    // do stuff when panning ends
});

$(".inner-box").hammer().bind("panright", function(event){
    // do stuff when panning
    // panning here should only affect the inner box
});
$(".inner-box").hammer().bind("panend", function(event){
    // do stuff when panning ends
});

任何建议或技巧?谢谢!
7个回答

8
在Hammer 2.0.6中,正如其他人所回答的那样,您可以调用event.srcEvent.stopPropagation()。但有一个注意点,根据文档,您必须设置domEvents=true

使用选项domEvents: true,Hammer能够触发DOM事件。这将为您提供像stopPropagation()这样的方法,因此您可以使用事件委托。 Hammer不会取消绑定的事件。

示例代码

var mc = new Hammer.Manager(elem);
mc.options.domEvents=true; // enable dom events
var pinch = new Hammer.Pinch();
mc.add(pinch);
mc.get('pinch').set({ enable: true });
mc.on("pinch",function(e){e.srcEvent.stopPropagation();});

或者

var hammertime = new Hammer(elem);
hammertime.domEvents = true;
hammertime.on("panstart", function(e){e.srcEvent.stopPropagation();});

这种技术在文档的提示页面上有列出,此处http://hammerjs.github.io/tips/


(注意:格式已调整,但不影响实际含义)

5
尝试使用event.srcEvent.stopPropagation()。Hammer将其包装在本机事件对象周围; srcEvent让您访问事件对象的“通常”属性。

3
我遇到了同样的问题,具体来说是嵌套的 Hammer 组件没有正确地停止传播。在我的情况下,我想要一个模态容器(它是最高级别的父组件,全屏并带有不透明的黑色背景)来处理关闭整个模态框的点击事件。子组件保存内容,我希望取消这些子组件的传播。换句话说,期望的行为是:模态框内的点击无效,但模态框外的点击会关闭模态框。
这进一步被 react-hammerjs 库所复杂化,它添加了一个额外的抽象层,包括 可能的错误报告,表明事件传播不正确。
无论我做了什么,我都不能让 stopPropagation() 起作用。即使将 options.domEvents 设置为 true,我也试图深入探究 event.srcEvent.stopPropagation()(和变种),但没有成功。
我发现使用 stopImmediatePropagation() 可以按预期工作,无论 domEvents 设置如何。我知道 stopImmediatePropagation() 可能更加极端,但我没有遇到任何副作用。子元素(如按钮)内的单击处理程序仍然正常工作,我可以通过单击容器来取消模态框。
以下是我的最终代码片段:
const myComponent = (props) => (
   <Hammer onTap={() => { ... cancel modal ... }} >
      <div className={'modal-container'} >
         <Hammer onTap={(e) => e.srcEvent.stopImmediatePropagation()}>
            <div className={'modal-content'}>
               ... modal content
               <Hammer onTap={() => { ... button handler ... }}>
                  <button>Take Action</button>
               </Hammer>
            </div>
         </Hammer>
      </div>
   </Hammer>
)

1
stopImmediatePropagation 对我有用,当只使用 stopPropagation 时不起作用。谢谢! - Cully
起初,stopImmediatePropagation 对我也起作用。但最终它带来了我无法解释的副作用。一旦它被调用一次,外部元素的处理程序将不会触发,即使其他点击事件应该由它捕获。最终我决定不使用它,而是在 srcEvent 中设置一个新属性,较高级别可以查找它,因为它是冒泡的。在某种程度上更干净,但在另一个方面则不太好。现在我必须标准化此新属性以供任何上层级使用。但是正确注册处理程序的顺序很关键。谢谢。 - WeakPointer

2

很遗憾,stopPropagation()不起作用。你需要检查手势的目标,以了解事件是从哪里触发的。

例如:

$(parent_element).hammer().bind(gesture_type, function(event) {
    if (event.gesture.target.className === correctClass)
        doStuff();
});

1

那只是有效的:

$(".outer-box").hammer({
  preventDefault: true,
  domEvents: true
}).on("panright", function() { });

0

遇到了同样的问题,但是通过启用domEvents来解决了。

Hammer.defaults.domEvents = true;

一旦启用,event.stopPropagation(); 就可以正常工作。


0

我曾经遇到过类似的情况,即我有两个可滑动容器叠在一起,只想让顶部的容器处理事件。但不知为何,event.srcEvent.stopPropagation 并没有起作用。

后来我发现,有一个名为 propagating-hammerjs 的库可以扩展 Hammer.js 的事件传播功能。我将其引入我的项目中,问题得以解决。


1
太糟糕了,我会停止使用HammerJs。 - br4nnigan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接