如果任何一个子节点获得焦点,则阻止触发模糊事件

Thw*_*esy 25 javascript jquery onblur knockout.js

我在页面上有一个div,显示有关特定类别(图像,名称等)的一些信息.

当我点击编辑图像时,它会将类别置于编辑模式,这样我就可以更新名称.从下图中可以看出,它显示"Soup"当前处于编辑模式,其他处于正常视图模式.这一切都按预期工作,取消/保存按钮做正确的事情.(我尝试添加图像,但不会让我,需要更多的爱)

然而,一旦处于编辑模式,如果我点击页面上的任何其他位置(div之外),预期结果将是汤类别将返回查看模式.在某种事件发生后,这也应该让我问他们是否想要保存更改.

所以我接下来决定在"汤"父div上创建一个模糊事件.如果我单击页面上的任何位置,这将按预期工作,但是如果我单击div的内部元素,它也会导致父模糊事件被触发,从而导致类别返回到查看模式.

那么,有没有办法阻止父div在其任何一个子节点获得焦点时触发模糊事件?

<div tabindex="-1" onblur="alert('outer')">
    <input type="text" value="Soup" />
</div>
Run Code Online (Sandbox Code Playgroud)

我只是在没有编译器的情况下编写代码,所以不确定这是否有效,但希望你能得到这个想法.

我正在使用Knockout.js动态更新GUI,但这不应该影响这个我不会想到的答案.

小智 69

我遇到了同样的问题。这对我有用。

 handleBlur(event) {
    // if the blur was because of outside focus
    // currentTarget is the parent element, relatedTarget is the clicked element
    if (!event.currentTarget.contains(event.relatedTarget)) {
        .....
    }
}
Run Code Online (Sandbox Code Playgroud)

享受 :)

  • 如果您遇到 Typescript 的输入问题(“‘EventTarget’类型的参数不可分配给‘Node’类型的参数。”),您可以将其写为“currentTarget.contains(e.latedTarget as Node)” (11认同)
  • 如果相关目标始终为空,则需要向目标添加可聚焦元素。/sf/ask/2993514611/ (2认同)

jba*_*bey 36

我以前必须解决这个问题.我不确定它是否是最好的解决方案,但它是我最终使用的.

由于点击事件在模糊之后触发,因此没有(跨浏览器,可靠)方式来判断哪些元素正在获得焦点.

然而,Mousedown在模糊之前开火.这意味着您可以在子元素的mousedown中设置一些标记,并在父模糊中查询该标记.

工作示例:http://jsfiddle.net/L5Cts/

请注意,keydown如果您还想捕捉键盘引起的模糊,您还必须处理(并检查tab/shift-tab).

  • 先生,你是一位绅士和学者.一年多以来,我一直在不同的情况下尝试不同的解决方案.感谢一百万人,从未意识到所有活动的时间安排. (4认同)

Rob*_*opp 17

我不认为mousedown在所有浏览器中的焦点事件之前都会有任何保证,所以更好的方法是使用它evt.relatedTarget.对于该focusin事件,该eventTarget属性是对当前失去焦点的元素的引用.您可以检查该元素是否是父元素的后代,如果不是,则您知道焦点是从外部进入父元素.对于focusout事件,relatedTarget是对当前正在接收焦点的元素的引用.使用相同的逻辑来确定焦点是否完全离开父节点:

const parent = document.getElementById('parent');

parent.addEventListener('focusin', e => {
    const enteringParent = !parent.contains(e.relatedTarget);

    if (enteringParent) {
        // do things in response to focus on any child of the parent or the parent itself
    }
});

parent.addEventListener('focusout', e => {
    const leavingParent = !parent.contains(e.relatedTarget);

    if (leavingParent) {
        // do things in response to fully leaving the parent element and all of its children
    }
});
Run Code Online (Sandbox Code Playgroud)

  • @WouldBeNerd React 中的合成 onBlur / onFocus 事件会冒泡(就像它们的原生表兄弟 focusout / fousin 一样),因此您可以在 React 中使用这些事件: `&lt;div onBlur={event =&gt; { if (!event.currentTarget.contains( event. relatedTarget)) doStuff(); }} /&gt;` 顺便说一句,你_可以_在 React 中使用本机事件;你只需要获取一个“ref”并调用“addEventListener”(可以将其包装在[hook](https://github.com/teetotum/react-panoply/blob/master/src/useEvent/index.js )) (6认同)
  • 由于完整性,应该接受答案。 (3认同)
  • react不允许使用focusin或focusout:/ (3认同)