jQuery keydown 回调仅监听外部 <ul> 而不是内部 <li> 元素

jQuery keydown callback listens only on outer <ul> rather than inner <li> element

嘿,这是我制作的代码演示

<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
</head>
<body>
<ul contenteditable class="outerList">
<li class="innerElement">Hello</li>
<li class="innerElement">World</li>
<li class="innerElement">Hello World</li>
</ul>
<script>
    $(".outerList").keydown(function () {
      console.log("I am the outer ul");
    });
    $(".innerElement").keydown(function() {
      console.log("I am an inner element");
    });
    </script>
</body>
</html>

这里是 运行 的 jsFiddle

http://jsfiddle.net/scrbovyr/

基本上我有一个内容可编辑的 UL,我想捕捉回车键并传入我自己的自定义函数。但我需要知道在哪个 LI 元素上引发了 keydown 事件。如演示中所示,我似乎只能将 keydown 事件侦听器(或与此相关的任何事件侦听器)绑定到外部 UL 元素。有没有办法将 keydown 事件附加到每个 LI?或者至少有一种方法可以将它附加到 UL,但仍然可以分辨出它来自哪个 child?

提前致谢,如果有任何其他信息有帮助,请告诉我!

您必须将 contenteditable 添加到您的 li 元素才能实现这一点。您将 contenteditable 设置为 ul 元素,因此事件将绑定到该元素,您可以编辑 li 元素,但它们没有设置 contenteditable , 因此不会为这些元素触发键盘事件。

<ul class="outerList">
    <li contenteditable class="innerElement">Hello</li>
    <li contenteditable class="innerElement">World</li>
    <li contenteditable class="innerElement">Hello World</li>
</ul>

然后:

$(".innerElement").keydown(function() {
  console.log("I am an inner element");
});

您可以勾选当前选择的节点

如果您不想让每个 li 成为一个 contenteditable 元素,您可以获取当前选择或插入符号位置的元素并对其进行检查。

嵌入式示例显示了如何使用 Web API Interface for contenteditable selections 实现此目的。 (我在Chrome中对此进行了测试,但它可能需要额外的逻辑来实现跨浏览器兼容性)。

还值得注意的是,您 可以 一些 事件侦听器绑定到 contenteditable 元素的子元素。例如,click 事件可能绑定到 li 元素,如您在嵌入式示例中所见。

$(document).ready(function() {
    
    function getCurrentNode() {
        var node = window.getSelection().getRangeAt(0).commonAncestorContainer;
        return node.nodeType === 1 ? node : node.parentNode;     
    }
    $('.outerList').on('click keyup', function (e) {
        var $target  = $(getCurrentNode()),
            $closest = $target.closest('b');
        console.log(e.type);
        console.log('I am the outer ul');
        console.log($target);
        
        // Optional. Filter by clostest selector.
        if ($closest.length) {
            console.log('Target matches selector', $closest);
        }
    });
    $('.innerElement').on('click', function (e) {
        console.log(e.type);
        console.log('I am an inner element');
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul contenteditable class="outerList">
      <li class="innerElement">Hello</li>
      <li class="innerElement"><i>Hello</i></li>
      <li class="innerElement"><b><i>Hello</i></b></li>
      <li class="innerElement"><b>Hello</b></li>
      <li class="innerElement">Hello</li>
      <li class="innerElement">Hello</li>
  </ul>