如何在jQuery中形式化/组织大量的eventHandler?

时间:2016-09-15 15:19:06

标签: javascript jquery mouseover

我是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>
&#13;
&#13;
&#13;

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

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

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

makeAllMouseover(todo)

我想我错过了关于html / js的一些非常明显但我无法弄清楚是什么/为什么......

3 个答案:

答案 0 :(得分:2)

只要你的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>

答案 1 :(得分:1)

我首先不使用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>

答案 2 :(得分:0)

您可以使用以下第一个片段自行分别对每个元素应用效果,或者,您可以使用第二个片段自动为您执行此操作:

第一个代码段 (适用于第一个代码段)

&#13;
&#13;
/* ----- 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");
&#13;
<!----- 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>
&#13;
&#13;
&#13;

第二个代码段 (适用于每一个)

&#13;
&#13;
/* ----- 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);
});
&#13;
<!----- 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>
&#13;
&#13;
&#13;

第二个脚本的较短代码:

&#13;
&#13;
/* ----- 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);
});
&#13;
<!----- 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>
&#13;
&#13;
&#13;

备注:

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

  2. 您可以使用 mouseover ,而不是使用 mouseout hover 。它有两个参数,都是函数,对应于 mouseover mouseout ,分别对应 hover(mouseover, mouseout)

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