【问题标题】:How to formalize/organize a massive amount of eventHandler in jQuery?如何在 jQuery 中规范化/组织大量事件处理程序?
【发布时间】:2016-09-15 15:19:05
【问题描述】:

我是 JavaScript 新手,不知道如何编写大量的 eventHandler,例如 mouseover/mouseout

想象一下,我必须在页面上键入元素。每个元素都应该触发一个特定的事件。我是否必须为每个元素编写每个函数,或者有一种方法可以将它们抽象出来,以便它们由另一个函数生成。

这是一个包含两个元素的两个列表的示例,但是我正在考虑每个列表有数百个元素的情况。

<!-- List 1 -->
    <div id="a">the A</div>
    <div id="b">the B</div>
    <!-- List 2 -->
    <div id="i">the I</div>
    <div id="j">the J</div>

    <script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
    <script>
    $( '#a' )
        .mouseover(function() {
            $( '#i' ).css("color", "red")
        })
        .mouseout(function() {
            $( '#i' ).css("color", "black")
        })

    $( '#b')
        .mouseover(function() {
            $( '#j' ).css("color", "red")
        })
        .mouseout(function() {
            $( '#j' ).css("color", "black")
        })

    $( '#j')
        .mouseover(function() {
            $( '#a' ).css("color", "red")
            $( '#i' ).css("color", "red")
        })
        .mouseout(function() {
            $( '#a' ).css("color", "black")
            $( '#i' ).css("color", "black")
        })
    </script>

我怎样才能简单地使用这样的数组,它代表我想要的交互:

var todo = [
    [a, [i]],
    [b, [j]],
    [j, [a, i]]
]

还有一个可以同时实现它们的函数:

makeAllMouseover(todo)

我想我遗漏了一些关于 html/js 的非常明显的东西,但我不知道是什么/为什么...

【问题讨论】:

  • 考虑到多人回答这个问题所付出的努力,我有点惊讶你根本没有评论、投票或接受任何答案。 TBH 有点令人失望!
  • 我仍在尝试不同的答案:p。考虑到反对票的数量,我有点不知道该怎么办......
  • 忽略反对票。选择最适合你的。如果您出于某种原因需要您的todo 数组,请选择@JamieBarker 的答案。如果您只是 认为 这就是您所需要的,但很乐意在您的 html 中添加一些标记,而不是使用我的。两者都可以正常工作。我想说的是不要使用需要switch 的那个,也不要使用每次鼠标悬停/移出时循环整个数组的那个。

标签: javascript jquery mouseover


【解决方案1】:

只要你的 todo 数组不改变格式,下面的内容应该可以动态地处理你扔给它的任何东西。

var todo = [
  ['a', ['i']],
  ['b', ['j']],
  ['j', ['a', 'i']]
];

todo.forEach(function(el) { // Loop through the array
  $('#' + el[0]).hover(function() { // MouseIn 
    $('#' + el[1].join(', #')).addClass('makeRed'); // Stringify the targets to add the class
  }, function() { // MouseOut
    $('#' + el[1].join(', #')).removeClass('makeRed'); // Stringify the targets to remove the class
  });
});
div {
  border-bottom: 1px solid black;
  color: black;  
}

.makeRed {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="listContainer">
<!-- List 1 -->
<div id="a">the A</div>
<div id="b">the B</div>
<!-- List 2 -->
<div id="i">the I</div>
<div id="j">the J</div>

JamieC 提出了一个有效的观点,即不使用 ID 来定位事件处理程序。我建议更进一步并使用event delegation,这样页面中只会添加一个侦听器,而不是为每个元素添加多个侦听器:

var todo = [
  ['a', ['i']],
  ['b', ['j']],
  ['j', ['a', 'i']]
];

function hoverText(id, isIn) {
  // Filter the array to just contain the one we've clicked
  var elements = todo.filter(function(value) {
    return id === value[0]
  })[0];

  // If the array is found, add/remove the class to/from the target elements
  if (elements) {
    elements = $('#' + elements[1].join(', #'));
     if (isIn) {
       elements.addClass('makeRed');
     } else {
       elements.removeClass('makeRed');
     }
   }
}

/**
 * Add event listener to the nearest element that surrounds all list items
 * Delegate the action to the list item(s).
 */
$('.listContainer').on('mouseenter', '.listItem', function(event) {
  hoverText(event.target.id, true)
}).on('mouseleave', '.listItem', function(event) {
  hoverText(event.target.id, false)
});
.listContainer .listItem {
  border-bottom: 1px solid black;
  color: black;
}
.listContainer .listItem.makeRed {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="listContainer">
  <!-- List 1 -->
  <div class="listItem" id="a">the A</div>
  <div class="listItem" id="b">the B</div>
  <!-- List 2 -->
  <div class="listItem" id="i">the I</div>
  <div class="listItem" id="j">the J</div>
</div>

【讨论】:

  • 为什么会有消极情绪?
  • 我也不知道,这个问题有一些奇怪的投票。
  • @mazieres 我用 JamieC 从他的回答中得到的一些有用的观点更新了这个答案,并对其进行了扩展以减少潜在内存分配的大小。我希望所有(或部分)这些糟糕的答案对你有所帮助。 ;)
  • 天哪,这是一个糟糕的答案。它真的值得它拥有的downvotes。你没有表现出任何努力无论如何。 ;)
  • 该死的你赢了!现在想想你自己是我的死对头!
【解决方案2】:

我会首先不使用 id 来定位事件处理程序 - 使用共享类,并且我也不会使用数组/映射来表示您的交互。使用一些data-* 属性来表示元素之间的关联要容易得多

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- List 1 -->
    <div id="a" class="mouse-action" data-highlight="#i">the A</div>
    <div id="b" class="mouse-action" data-highlight="#j">the B</div>
    <!-- List 2 -->
    <div id="i" class="mouse-action">the I</div>
    <div id="j" class="mouse-action" data-highlight="#a, #b">the J</div>

    <script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
    <script>
      $(".mouse-action")
        .mouseover(function() {
            $( $(this).data("highlight") ).css("color", "red")
        })
        .mouseout(function() {
            $( $(this).data("highlight") ).css("color", "black")
        })
    </script>

【讨论】:

  • 很想知道为什么 dv 在这里。这种方式更容易,而且我之前用这个解决方案回答了 10 次类似的问题,效果很好。
  • 抱歉,我正准备发表评论,保证!这可以完成工作,但它没有回答 OP 的问题:“我怎样才能简单地使用像 this 这样的数组,它代表我想要的交互”跨度>
  • @JamieBarker 如果一个业余/新手木匠问专业人士如何用他们的鞋子敲钉子 - 专业人士总是会指出一把锤子,以及如何正确使用它。
  • 您提出了一个有效的观点,但我们只能猜测 OP 的 actual 目标是什么,以及他们的 actual 代码是什么,因为他们我只给出了示例数据:/
  • @JamieBarker 谢谢 - 这一点对我来说是关键I guess I'm missing something pretty obvious about html/js - 他们遗漏了一些非常明显的东西。这是 XY 问题的一个子集(我认为我需要 X 来做 Y)。
【解决方案3】:

您可以使用以下 sn-ps 中的第一个单独将您想要的效果应用到每个元素,或者,您可以使用第二个自动为您执行此操作:

第一个片段: (应用于第一个)

/* ----- JavaScript ----- */
function change(selector) {
  var affected, hoverColor;
  switch (selector) {
    case "#a":
      affected = ["#i"];
      hoverColor = "red";
      break;
    case "#b":
      affected = ["#j"];
      hoverColor = "blue";
      break;
    case "#j":
      affected = ["#a", "#i"];
      hoverColor = "yellow";
      break;
  }

  $(selector).hover(function() {
    for (var i = 0; i < affected.length; i++) $(affected[i]).css("color", hoverColor)
  }, function() {
    for (var i = 0; i < affected.length; i++) $(affected[i]).css("color", "black")
  });
}

/* APPLY THE EFFECT */
change("#a");
<!----- HTML ----->
<!-- List 1 -->
<div id="a">the A</div>
<div id="b">the B</div>
<!-- List 2 -->
<div id="i">the I</div>
<div id="j">the J</div>

<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>

第二个片段: (适用于每个片段)

/* ----- JavaScript ----- */
["#a", "#b", "#j"].forEach(function(each) {
  (function(selector) {
    var affected, hoverColor;
    switch (selector) {
      case "#a":
        affected = ["#i"];
        hoverColor = "red";
        break;
      case "#b":
        affected = ["#j"];
        hoverColor = "blue";
        break;
      case "#j":
        affected = ["#a", "#i"];
        hoverColor = "yellow";
        break;
    }

    $(selector).hover(function() {
      for (var i = 0; i < affected.length; i++) $(affected[i]).css("color", hoverColor)
    }, function() {
      for (var i = 0; i < affected.length; i++) $(affected[i]).css("color", "black")
    });
  })(each);
});
<!----- HTML ----->
<!-- List 1 -->
<div id="a">the A</div>
<div id="b">the B</div>
<!-- List 2 -->
<div id="i">the I</div>
<div id="j">the J</div>

<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>

第二个脚本的代码更短:

/* ----- JavaScript ----- */
["#a", "#b", "#j"].forEach(function(each) {
  (function(s) {
    var
      aff = (s === "#a") ? ["#i"] : ((s === "#b") ? ["#j"] : ((s === "#j") ? ["#a", "#i"] : "")),
      hovColor = (s === "#a") ? "red" : ((s === "#b") ? "blue" : ((s === "#j") ? "yellow" : "")),
      unhover;

    $(s).hover(changeColor, changeColor);
    
    function changeColor () {
      for (var i = 0; i < aff.length; i++) $(aff[i]).css("color", (unhover) ? "black" : hovColor);
      unhover = !unhover;
    }
  })(each);
});
<!----- HTML ----->
<!-- List 1 -->
<div id="a">the A</div>
<div id="b">the B</div>
<!-- List 2 -->
<div id="i">the I</div>
<div id="j">the J</div>

<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>

注意事项:

  1. 对于 affected 变量,我使用数组 (affected = ["#i"]) 而不是字符串 (affected = "#i"),这样我们就可以利用数组的 length 属性并使用 for 循环以确保第三种情况的两个元素都获得所需的效果。

  2. 您可以使用 hover 而不是使用 mouseovermouseout,它接受两个参数,两者是函数,分别对应mouseovermouseout(hover(mouseover, mouseout))

  3. switch 语句是硬编码的,这意味着如果您想添加更多元素,您必须为每个元素创建一个新案例,并且还要添加 在 sn-p 开头的 forEach 之前的数组中,您要使用 hover 的每个元素的id

【讨论】:

  • OP 要求通过简单地提供数据数组来动态实现交互:“我怎样才能简单地使用这样的数组,它代表我想要的交互”。您的两个示例都没有使用数据来生成交互,也不是动态的。如果提供的数据发生变化,您将不得不更新 JavaScript 代码以匹配,并且不能使用动态数据,例如待办事项列表。
  • 感谢您告诉我@JamieBarker。您的答案更好,而且确实是动态的。我赞成:)
猜你喜欢
  • 2013-10-24
  • 2013-06-05
  • 1970-01-01
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-23
  • 1970-01-01
相关资源
最近更新 更多