Backbone.js悬停事件未触发

时间:2012-01-19 13:32:37

标签: javascript jquery backbone.js

我第一次尝试使用Backbone.js,我遇到了一些麻烦。我不知道我的问题是我是不是在理解骨干应该如何工作,或者它只是一个代码问题。

我正在尝试创建一个动态菜单,使用它的项目创建主菜单栏没有问题,但是当我将其中一个菜单项悬停时,我无法触发悬停事件。

视图

var MenuView = Backbone.View.extend({
    initialize: function(items) {
        this.menu = items;
        //Main navigation bar
        this.el = $("#main-nav");
        this.trigger('start');
        this.render();
    },
    render: function() {
        var me = this;
        _.each(this.menu, function(mi) {
            mi.render(me.el);
        });
        return this;
    },
    handleHover: function(e) {
        console.debug(e);
    }
});

var MenuItemView = Backbone.View.extend({
    tagName: 'li',
    className:'menu-item',
    events: { //none of these work
        'hover a':'handleHover',
        'mouseover a':'handleHover',
        'mouseover':'handleHover',
        'click': 'handleHover',
        'click a': 'handleHover'
    },
    initialize: function(mi) {
        this.menuItem = mi;
        this.el = $("<li class=\"menu-item\"></li>")
    }, 
    render: function(parent) {
        this.el.append('<a href="' + this.menuItem.get("link") + '">' + this.menuItem.get("text") + '</a>');
        parent.append(this.el);
        return this;
    },

    handleHover: function(ev) {
        console.debug("Hovering! " + ev + this.menuItem.get("cid"));
        console.debug(ev);
        return false;
    }
});

模型

var MenuItem = Backbone.Model.extend({
    defaults: {
        parent: null,
        children: [],
        link: "",
        text: ""
    }   
});

启动代码

$(document).ready(function() {
    var menu = new MenuView([
        new MenuItemView( new MenuItem({link: "/", text: "Home"})),
        new MenuItemView( new MenuItem({link: "/", text: "Users"})),
        new MenuItemView( new MenuItem({link: "/", text: "Configuration"}))
    ]);
});

任何帮助将不胜感激!

谢谢!

更新

好的,在MenuItemView视图上取el方法之外的initialize定义之后,它可以工作,但同一个元素在视图的所有实例上都被重用,所以我不得不改变以下代码的视图,以使其按照我想要的方式工作:

 var MenuItemView = Backbone.View.extend({

    events: { //none of these work
        'hover a':'handleHover',
        'mouseover a':'handleHover',
        'mouseover':'handleHover',
        'click': 'handleHover',
        'click a': 'handleHover'
    },
    el: $('<li class="menu-item"></li>'),
    initialize: function(mi) {
        this.menuItem = mi;
        this.el = $(this.el).clone(true);
    }, 
    render: function(parent) {
        this.el.append('<a href="' + this.menuItem.get("link") + '">' + this.menuItem.get("text") + '</a>');
        parent.append(this.el);
        return this;
    },

    handleHover: function(ev) {
        console.debug("Hovering! " + ev + this.menuItem.get("cid"));
        console.debug(ev);
        return false;
    }
});

我必须在新实例上克隆元素吗?

3 个答案:

答案 0 :(得分:10)

悬停不是正常事件,而是jquery提供的“便利”事件。它是mouseenter和mouseleave的结合。

绑定到mouseenter和mouseleave而不是悬停将满足你的需要。

答案 1 :(得分:8)

Re:“为什么我必须在新实例上克隆元素?”

基本问题就在这里:

var MenuItemView = Backbone.View.extend({
    // ...
    el: $('<li class="menu-item"></li>'),

在定义$('<li class="menu-item"></li>')时执行MenuItemView调用,因此您最终只能在$('<li>')的所有实例之间共享一个MenuItemView

如果您在elinitialize内创建render,那么您必须使用delegateEvents手动绑定事件:

  

默认情况下,在{...]

的View构造函数中调用delegateEvents

因此,如果您自己创建this.el,那么您必须自己致电this.delegateEvents()。例如:

var MenuItemView = Backbone.View.extend({
    // ...
    render: function() {
        this.el = $('<li class="menu-item"><a>' + this.cid + '</a></li>');
        this.delegateEvents();
        return this;
    },
    //...
});

演示:http://jsfiddle.net/ambiguous/RPqMh/2/

但是,如果您this.el withDataAndEvents开启了var MenuItemView = Backbone.View.extend({ el: $('<li class="menu-item"></li>'), // ... initialize: function() { this.el = this.el.clone(true); this.el.append('<a>' + this.cid + '</a>'); }, //... }); 标记,那么您应该没问题:

this.el.clone()

演示:clone

但是如果你只是var MenuItemView = Backbone.View.extend({ el: $('<li class="menu-item"></li>'), // ... initialize: function() { this.el = this.el.clone(); this.el.append('<a>' + this.cid + '</a>'); }, // ... }); ,它将无效,因为http://jsfiddle.net/ambiguous/hCW3F/1/不会绑定到克隆:

delegateEvents

演示:delegate

但是如果你添加自己的var MenuItemView = Backbone.View.extend({ el: $('<li class="menu-item"></li>'), // ... initialize: function() { this.el = this.el.clone(); this.el.append('<a>' + this.cid + '</a>'); }, render: function() { this.delegateEvents(); return this; }, // ... }); 电话,你就可以了:

{{1}}

演示:http://jsfiddle.net/ambiguous/KZNPA/

答案 2 :(得分:2)

在我看来,你不需要这个属性:

tagName: 'li',
className:'menu-item'
如果您指定this.el = $('<li class="menu-item"></li>');

,请在MenuItemView中