2012-01-19 49 views
3

我想第一次使用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"})) 
    ]); 
}); 

任何帮助将不胜感激!

谢谢!

更新

好,服用elinitialize方法的定义上MenuItemView视图后,它的工作原理,但相同的元素得到重用的视图的所有实例,所以我不得不改变为了视图到下面的代码,使其工作的方式,我希望它:

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; 
    } 
}); 

WNY我必须克隆一个新实例的元素?

+0

你为什么要克隆你的'el'?考虑'$('

  • ')'是否被评估,你会得到你的答案。 –

    +0

    如果我在'initialize'方法中为'el'创建元素,那么事件不会被触发,我该如何解决这个问题? – Deleteman

    回答

    8

    回复:“为什么我必须克隆新实例上的元素?”

    根本问题就在这里:当MenuItemView被定义所以你最终只有一个$('<li>')被跨越的MenuItemView所有实例共享执行

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

    $('<li class="menu-item"></li>')电话。

    如果创建内部initializerenderel那么你就必须使用delegateEvents结合手工事件:

    默认情况下,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/

    然而,如果你clonethis.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>'); 
        }, 
        //... 
    }); 
    

    演示:http://jsfiddle.net/ambiguous/hCW3F/1/

    但如果你只是this.el.clone(),它将无法正常工作,因为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>'); 
        }, 
        // ... 
    }); 
    

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

    但是如果你添加自己的delegateEvents通话,你会好起来的:

    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; 
        }, 
        // ... 
    }); 
    

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

    +0

    非常感谢您的解释!它为我清除了整个事情:) – Deleteman

    +0

    @Deleteman:我必须确保我的头脑清楚,所以我分享了我的笔记:) –

    2

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

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

    ;

    +0

    是的,在测试过程中添加的代码只是为了检查是否能解决我的问题,但它没有... – Deleteman

    +0

    是的,我也检查过。没有修复。无论如何,而不是'tagName'和'className'直接定义'el:$('

  • ')'它应该可以工作。 – dfsq

    +0

    是的,在'initialize'方法之外定义'el'工作(种类),但是同一个元素在视图的每个实例上被重用。我会写一个更新,以显示你... – Deleteman

    9

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

    绑定到mouseenter和mouseleave而不是悬停会执行您所需的操作。