javascript - 发生滚动事件时防止将鼠标悬停在元素上

标签 javascript events backbone.js marionette

我使用backbone/marionette构建了一个下拉小部件,可以让您使用键盘在下拉列表中上下导航。我需要区分选定和突出显示,因此我将 bool 值存储在列表项模型的 isSelected 和 isHighlighted 中。每当该项目悬停时,isHighlighted 就会更改为 true。

这是我的问题,我已经将下拉列表设置为具有 maxItem,因此当下拉列表中的项目太多时,我会显示一个滚动条,以便人们可以滚动以查看更多列表项目。当我使用键盘导航导航通过 maxItem 限制时,我会调用 animate 并滚动顶部一定距离,以便突出显示的内容保持在 View 中。问题是,如果我碰巧将鼠标放在下拉列表中并且发生了滚动,它将在鼠标指针所在的项目上触发 mouseenter 事件。然后它会将悬停元素的 isHighlighted 更改为 true。这意味着突出显示的项目会重新向上移动,当我使用键盘再次向下导航时,它将从顶部向下移动,而不是从之前的位置继续。

当滚动事件触发时,我是否可以阻止 mouseenter 事件?

尝试包含所有相关代码,希望这有帮助:

onKeyUp: function (event) {
    var key = event.which;

    switch (key) {
        case 38: // UP
            this.onUpArrow();
            break;
        case 40: // DOWN
            this.onDownArrow();
            break;
        default:
            // default method
    }
},
onDownArrow: function () {
    if (!this.isDropdownOpen()) {
        this.openDropdown();
    } else {
        this.dropdown.highlightNext();
        this.dropdown.scroll();
    }
},

在另一个文件中,我有

events: {
    'mouseenter': 'onMouseEnter'
},
onMouseEnter: function (event) {
    this.triggerMethod('dropdown:option:mouseenter', {
        event: event,
        view: this,
        model: this.model
    });
},

在另一个文件中,我有

onDropdownOptionMouseenter: function () {
    var data = _.last(arguments),
        event = data.event,
        view = data.view;
    view.highlight();
}

此时,发生了滚动,并且 mouseenter 触发器已被触发并且突出显示发生了变化。我只是不知道在哪里可以添加代码来阻止浏览器识别mouseenter。我应该为此添加自定义事件吗?在我看来,这是一项艰巨的工作,必须有一个更简单的解决方案。

最佳答案

设置事件聚合器

在 Backbone 中创建事件聚合器很简单,只需扩展事件对象即可,

window.vent = _.extend({}, Backbone.Events);

我们将事件聚合器 vent 附加到全局范围,以便任何人都可以监听。

如果您使用的是 Marionette,则可以使用内置 Marionette 消息传递系统 Backbone.Wreqr 中的内置聚合器(注意: Wreqr<从 Marionette v.3 开始, 将使用新的消息 API Radio 进行切换,但我从一个好的来源获得了它,更新管理器应该迁移所有 Wreqr 实例到 Radio)。

创建事件聚合器只需调用即可,

window.vent = new Backbone.Wreqr.EventAggregator();

现在为了解决您的问题,我们将使用事件聚合器来设置一个 pubsub 系统,您的项目 View 将订阅一个事件,以帮助它们正确地对滚动使用react。管理滚动的 View 将发布此事件。

注意: 如果您想创建独立的消息传递管道,Backbone.Wreqr也可以配备使用Channels。查看docs .

订阅

那么让我们设置订阅吧。在项目 View 中执行

initialize: function ()  {
  this.listenTo(vent, "dropdown:before:scroll", function() {
    this.isScrolling = true;
  }
  this.listenTo(vent, "dropdown:end:scroll", function() {
    this.isScrolling = false;
  }
}

发布

我们刚刚订阅的事件将在 scrollTop 调用之前和之后通过触发 vent 上的事件来发布。所以你可以像这样重写 maxlimit 检查器,

if (currItem > maxItem) {
  vent.trigger("dropdown:before:scroll");
  someElement.scrollTop();
  vent.trigger("dropdown:end:scroll");
}

监听这些事件的项目将知道您正在滚动,因为触发事件是同步并且会按正确的顺序触发。

防止高亮

最后,现在您正在发布 scrollTop 事件,并且您的项目正在监听该事件,您可以确保遇到 mouseenter 的项目知道何时 强调。

onMouseEnter: function (event) {
  if (!this.isScrolling) {
    this.triggerMethod('dropdown:option:mouseenter', {
        event: event,
        view: this,
        model: this.model
    });
  }
},

关于javascript - 发生滚动事件时防止将鼠标悬停在元素上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27829534/

相关文章:

javascript - 从 localStorage 中提取数字作为数字

javascript - 如何等待建立数据库连接并为数组中的每个数据库执行查询

javascript - 除了 render 方法之外,还有什么方法可以在 React 类中获取 props 吗?

javascript - 在 javascript 和 HTML 中从 ResourceBundle 中获取字符串

javascript - 如何为 html 集合中的每个元素添加事件监听器?

javascript - 实时事件和查询元素是否将响应事件

javascript - 如何从对象数组中获取属性?

javascript - Hammer Js 无法与 Backbone.js 一起使用

php - Laravel 5 中的钩子(Hook)?

javascript - 有没有办法在控制台自动输出所有的backbone.js触发器/事件?