Backbone.js悬停事件未触发

Del*_*man 4 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;
    }
});
Run Code Online (Sandbox Code Playgroud)

模型

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

启动代码

$(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"}))
    ]);
});
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激!

谢谢!

更新

好吧,在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;
    }
});
Run Code Online (Sandbox Code Playgroud)

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

Chr*_*son 10

悬停不是正常事件,而是由jquery提供的"便利"事件.它是mouseenter和mouseleave的组合.

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


mu *_*ort 8

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

根本问题就在这里:

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

$('<li class="menu-item"></li>')当执行调用MenuItemView被定义所以你最终只有一个$('<li>')是跨越的所有实例共享MenuItemView.

如果您创建el内部initialize,render则必须使用delegateEvents以下方法手动绑定事件:

默认情况下,delegateEvents在View的构造函数中为您调用[...]

因此,如果你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;
    },
    //...
});
Run Code Online (Sandbox Code Playgroud)

演示: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>');
    }, 
    //...
});
Run Code Online (Sandbox Code Playgroud)

演示: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>');
    }, 
    // ...
});
Run Code Online (Sandbox Code Playgroud)

演示: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;
    },
    // ...
});
Run Code Online (Sandbox Code Playgroud)

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