调用具有多个数组参数的函数

时间:2019-04-02 15:03:29

标签: javascript html css dom

有一个HTML锚点列表,我需要添加事件侦听器,据我了解,当我将其作为参数提及时,它并不能接收数组。

尝试使用自调用代替其他功能,但是这样i甚至在调试时也没有被监听。

for (var i=0; i < anc.length; i++) {
    anc[i].addEventListener('mouseover', function(i,pop,tri) {
       console.log('i=%i', i);    // last value of loop
       pop[i].style.display = 'initial';
       tri[i].style.animation='anim_dpt_tr 0.4s ease-out forwards';
    });
    ...
}

更有用的代码

var pop = document.querySelectorAll('#cities > li > a > .popup');
const anc = document.querySelectorAll('#cities > li > a');
var tri = document.getElementsByClassName('triangle-left');

for (var i=0; i < anc.length; i++) {
    anc[i].addEventListener('mouseover', over(i, tri, pop));
    anc[i].addEventListener('touchmove', over(i, tri, pop));
    anc[i].addEventListener('touchend', out(i, tri, pop));
    anc[i].addEventListener('mouseout', out(i, tri, pop));
}

function over(i,tri,pop) {
    console.log("over_address=%i", pop[i]); // =0
    pop[i].style.display = 'initial';
    tri[i].style.animation='anim_dpt_tr 0.4s ease-out forwards';
}
function out(i,tri,pop) {
    console.log("out_i=%i", i);             // =each index
    pop[i].style.display = 'none';
    tri[i].style.animation='anim_dpt_tr_back 0.3s ease-in forwards';
}

此处是HTML树

<ul id="cities">
  <li>
    <a href="">Shoulder
      <span class="triangle-left"></span> <span class="popup">Arm</span> </a>
  </li>
...

如何将数组正确传递给事件处理程序?

3 个答案:

答案 0 :(得分:3)

您的“更有用的代码”是错误的,因为它实际上并未分配任何事件处理程序;它只是立即调用代码并返回undefined

要采用这种方法,您需要让那些函数返回一个函数。在那定义事件参数。

function over(i,tri,pop) {
  return function(event) {
    console.log("over_address=%i", pop[i]); // =0
    pop[i].style.display = 'initial';
    tri[i].style.animation='anim_dpt_tr 0.4s ease-out forwards';
  }
}
function out(i,tri,pop) {
  return function(event) {
    console.log("out_i=%i", i);             // =each index
    pop[i].style.display = 'none';
    tri[i].style.animation='anim_dpt_tr_back 0.3s ease-in forwards';
  }
}

这是一种古老的做法。最近,您可以使用ifor而不是let,使用范围为const循环块的var变量。


要考虑的另一件事是,缓存集合是否真的值得。如果每个集合中每个i元素之间的布局都存在非常简单的关系,则首选在处理程序内部进行DOM遍历。


另一种可能性是创建一个实现 EventListener 接口的对象。然后,您可以将每个元素分配给对象,并使用对象本身代替事件处理程序功能。

var pop = document.querySelectorAll('#cities > li > a > .popup');
const anc = document.querySelectorAll('#cities > li > a');
var tri = document.getElementsByClassName('triangle-left');

for (var i=0; i < anc.length; i++) {
    // Create a new instance of your object, giving it the data needed
    //   when an event occurs.
    var obj = new MyElements(pop[i], anc[i], tri[i], i);

    // Use the object itself in lieu of an event handler function
    //  (see below)
    anc[i].addEventListener("mouseover", obj);
    anc[i].addEventListener("touchmove", obj);
    anc[i].addEventListener("mouseout", obj);
    anc[i].addEventListener("touchend", obj);
}

// Holds the relevant info for each index
function MyElements(pop, anc, tri, i) {
  this.pop = pop
  this.anc = anc
  this.tri = tri
  this.i = i
}

// Implements the EventListener interface.
// This is what gets invoked when an event occurs.
// It is set up to simply invoke a function on the same object
//   that has been given the same name as the event.
MyElements.prototype.handleEvent = function(event) {
  this[event.type](event)
}

// These are the functions for each event type. For simplicity, I
// gave each handler the name of the event that fires it so that
// you can use event.type to invoke them.
MyElements.prototype.mouseover = 
MyElements.prototype.touchmove = function over(event) {
    console.log("over_address=%i", this.i); // =0
    this.pop.style.display = 'initial';
    this.tri.style.animation='anim_dpt_tr 0.4s ease-out forwards';
}

MyElements.prototype.mouseout =
MyElements.prototype.touchend = function out(event) {
    console.log("out_i=%i",this.i);             // =each index
    pop[i].style.display = 'none';
    tri[i].style.animation='anim_dpt_tr_back 0.3s ease-in forwards';
}

答案 1 :(得分:0)

您可以使用.bind()完成此操作。您的所有通话可能看起来像,例如over.bind(null, i, tri, anc),用作函数处理程序时。注意,必需的null作为第一个参数。

因此,它将转换为:

over.bind(null, i, tri, pop)
out.bind(null, i, tri, pop)

让我知道是否可行。否则,给我留言。

答案 2 :(得分:0)

此行anc[i].addEventListener('anyEvent', over(i, tri, pop))将尝试立即调用该函数。相反,您可以创建一个回调函数并从中调用overout。同样,除了传递多个参数外,还使用this传递上下文。这里的this是指触发事件的元素,在这种情况下为anchor tag

然后在over/out函数内部使用elem.querySelector('.popup'),它将以触发事件的元素内部具有popup类的元素为目标。然后您可以添加样式属性

const anc = document.querySelectorAll('#cities > li > a');
for (var i = 0; i < anc.length; i++) {
  anc[i].addEventListener('mouseover', function() {
    over(this)
  });

  anc[i].addEventListener('mouseout', function() {
    out(this)
  });
}

function over(elem) {
  elem.querySelector('.popup').style.display = 'initial';
  elem.querySelector('.triangle-left').style.animation = 'anim_dpt_tr 0.4s ease-out forwards';
}

function out(elem) {
  elem.querySelector('.popup').style.display = 'none';
  elem.querySelector('.triangle-left').style.animation = 'anim_dpt_tr_back 0.3s ease-in forwards';
}
<ul id="cities">
  <li>
    <a href="">Shoulder
      <span class="triangle-left"></span> <span class="popup">Arm</span> </a>
  </li>
  <li>
    <a href="">Shoulder
      <span class="triangle-left"></span> <span class="popup">Leg</span> </a>
  </li>
  <li>
    <a href="">Shoulder
      <span class="triangle-left"></span> <span class="popup">ercerc</span> </a>
  </li>
</ul>