Javascript - 多次触发 keyup 事件

Javascript - keyup event firing multiple times

我正在使用 hotkeys plugin 向关键事件添加处理程序。 我制作了一个图片滑块,我可以在其中浏览杂志的封面图片。 我首先制作了一个脚本,用户可以通过单击导航按钮浏览杂志封面。

$(document).ready(function () {
  imagesIndex = 0,
  nextImage = 0,
  loadedImages = [];

  if (typeof images !== 'undefined') {

    preload();

    $('#forward').click(forwardClick);
    $('#back').click(backClick);
  }
});

var preload = function () {
  for (i = 0; i < 4; i++) {
    if (nextImage < images.length) {
        var img = new Image();
        img.src = '/imagecache/cover/' + images[nextImage];
        loadedImages[nextImage] = img;
        ++nextImage;
    }
  }
}

var forwardClick = function() {
  imagesIndex++;

  preload();
  $('#back').removeClass('not-allowed');

  if (imagesIndex > (loadedImages.length - 1)) {
      imagesIndex = loadedImages.length - 1;
  }

  if (imagesIndex > (loadedImages.length - 2)) {
      $('#forward').addClass('not-allowed');
  }

  $('#cover-image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
}

var backClick = function() {
  imagesIndex--;

  $('#forward').removeClass('not-allowed');

  if (imagesIndex < 0) {
      imagesIndex = 0;
  }

  if (imagesIndex < 1) {
      $('#back').addClass('not-allowed');
  }

  $('#cover-image').attr({"src" : loadedImages[imagesIndex].src, "alt" : name});
}

module.exports.preload = preload;
module.exports.forward = forwardClick;
module.exports.back = backClick;

效果很好,我有一系列杂志,当用户点击其中一个时,会滚动到创建用户点击的杂志详细信息的部分。每次用户点击某杂志时,我都会动态更改该部分,并使用被点击的杂志更新详细信息。用户可以通过点击导航按钮浏览该杂志的封面。 所以,每次用户点击一些新杂志时,我都会调用这个函数:

var showMagazineDetail = function showMagazineDetail(id, slug, name, summary, issueImage, magazineImage, visiolinkPrefix, page){
    images = [];
    nextImage = 0;
    imagesIndex = 0;
    loadedImages = [];

    ...rest of the code

我在这里清空 imagesloadedImages 数组。 所以,这部分工作正常。我遇到的问题是关键事件。 我制作了这个脚本,我在其中检查该部分是否在视口中,然后启用浏览杂志的封面。

var issueImages = require('./issue-images');
var forward = issueImages.forward;
var back = issueImages.back;

$(document).ready(function () {
  var coverImage = $('.magazine-hero');
  window.onscroll = function() {
    var coverVisible = isElementInViewport(coverImage);

    if (coverVisible) {
      $(document).on('keyup', null, 'right', forward);
      $(document).on('keyup', null, 'left', back);
    }
  };

});


function isElementInViewport(el) {
  var rect = el[0].getBoundingClientRect();

  return rect.bottom > rect.height*0.8 &&
        rect.top < ((window.innerHeight*0.7) || (document.documentElement.clientHeight*0.7)) &&
        rect.right > 0 &&
        rect.left < (window.innerWidth || document.documentElement.clientWidth);
}

问题是,当我按下键转到下一个封面时,它会立即转到杂志的最后一个封面。 当我在控制台中检查 imagesIndex 时,我可以看到在按下 right key arrow 时,index 立即转到 12(这是杂志的最后一个封面):

1 issue-images.js?828c:28 2 issue-images.js?828c:28 3 issue-images.js?828c:28 4 issue-images.js?828c:28 5 issue-images.js?828c:28 6 issue-images.js?828c:28 7 issue-images.js?828c:28 8 issue-images.js?828c:28 9 issue-images.js?828c:28 10 issue-images.js?828c:28 11 issue-images.js?828c:28 12

如 jquery 文档中所述 "The keydown event is sent to an element when the user presses a key on the keyboard. If the key is kept pressed, the event is sent every time the operating system repeats the key."

您转到最后一张图片,因为该函数被多次调用。

使用 keyup 事件而不是 keydown

$(document).on('keyup', null, 'right', forward);
$(document).on('keyup', null, 'left', back);

一次性设置您的活动

var issueImages = require('./issue-images');
var forward = issueImages.forward;
var back = issueImages.back;
var eventBinded = false;

$(document).ready(function () {
  var coverImage = $('.magazine-hero');
  window.onscroll = function() {
    var coverVisible = isElementInViewport(coverImage);

    if (coverVisible && !eventBinded ) {
      $(document).on('keydown', null, 'right', forward);
      $(document).on('keydown', null, 'left', back);
      eventBinded = true;
    }
  };
});