【问题标题】:Backbone JS View Events not Firing?骨干 JS 视图事件未触发?
【发布时间】:2011-04-28 23:37:37
【问题描述】:

我正在尝试使用 Backbone JS,到目前为止,一切似乎都很有意义并且工作顺利。

但是使用下面的代码,我的自定义事件似乎没有触发。以下代码中的任何内容都可以说明为什么会这样?我需要在视图中“初始化”任何东西吗?代码/结构上的任何其他指针也很酷。以下是我的完整 JS/HTML。

JS

var Todo = Backbone.Model.extend({});

var TodoCollection = Backbone.Collection.extend({

    model: Todo,
    url: '/Home/Todos'

});

var AppView = Backbone.View.extend({

    // where it should listen, required?
    el: $(".content"),

    events: {
        "keypress #new-todo": "enter"
    },

    initialize: function () {
        // _.bindAll(this, "render", "createOnEnter");
        // this.collection.bind("all", this.render);
    },

    hi: function () {
        alert('ohai');
    },

    render: function () {
        var lis = '';
        $.each(this.collection.models, function () {
            lis += '<li>' + this.get('Text') + '</li>';
        });
        $('#todo-list').append(lis);
        return this.el;
    },

    enter: function (e) {
        alert('hi');
    }

});


var TodoController = Backbone.Controller.extend({

    routes: {
        "": "todos"
    },

    initialize: function (options) { },

    todos: function () {
        var todolist = new TodoCollection();
        todolist.fetch({
            success: function (data) {
                var appview = new AppView({ collection: data });
                appview.render();
            }
        });
    }

});

$(function () {
    window.app = new TodoController();
    Backbone.history.start();
});

HTML

<div id="todoapp">
    <div class="content">
        <input id="new-todo" placeholder="What needs to be done?" type="text" />
        <div id="todos">
            <ul id="todo-list">
            </ul>
        </div>
        <a href="#">say hey</a>
    </div>
</div>

【问题讨论】:

    标签: jquery backbone.js


    【解决方案1】:
    el: $(".content")
    

    试试这个:

    var appview = new AppView({ el:$(".content"), collection: data });
    

    您不能在那里调用 jQuery,因为尚未创建 DOM。当视图作为我的示例或在初始化中加载时,您必须这样做。

    【讨论】:

    • 感谢您的回答。我仍然有点困惑,为什么那时不会创建 DOM。我在底部启动控制器并将其包装在文档就绪调用中。然后我的控制器通知了 AppView,所以那不是第一次调用 'el' 吗?
    • var AppView = Backbone.View.extend({}) 在浏览器读取时进行评估。您在文档就绪调用中对其进行实例化,但由于 el 不是函数,因此它将作为扩展的一部分进行评估。
    • 谁能解释一下为什么 Backbone.js Todo 示例在创建 AppView 时不需要传入参数?他们在 todo.js 的顶部有这样的注释,“// DOM 准备好后加载应用程序,使用 jQuery.ready:”,但我没有看到他们做任何事情来确保 DOM 准备好。谢谢。
    • 没关系。我想我想通了。这是因为他们将所有内容都包装在 $(function {}); 中,对吗?
    • 而不是el: $('.content'),你可以做el: '.content',没有包装,然后你不需要每次创建视图时传递它。初始化时,主干将字符串包装在$() 中。这是一个比每次创建视图时都传递它更好的解决方案。
    【解决方案2】:

    此外,为了让您的事件生效,您必须将渲染函数中的内容绑定到 this.el。事件都绑定到您指定的元素,因此您需要将您的事件生成元素作为子元素绑定到充当委托者的元素。

    【讨论】:

    • 我想要这个评论两次,但我不能,这正是我的问题,10 倍!
    • 随着 Backbone API 的更新,这种情况现在也发生了变化。现在有一种方法可用于动态设置 el,如果使用该方法,则该函数会自动调用 delegateEvents()。
    • 我不太了解主干,但我认为这可以通过不指定 el 属性并在渲染函数内部执行 $('.content').wrap(this.el) 来解决;
    • +1 ! “因此,您需要将您的事件生成元素作为子元素绑定到充当委托者的元素。”提高了我对 el 和事件的理解
    【解决方案3】:

    批准的答案有一个缺点。如果你设置 { el: $(".content") },你就不会很有活力。无法在 DOM 中重用“.content”元素。只要您在此视图上调用 remove(),$(".content") 也会消失。

    我使用另一个参数来传递该信息:

    { renderTarget: $("#content") }.
    

    并在渲染开始时将我的视图插入 DOM:

    initialize: function (options) { 
        options = options || {}; 
        this.renderTarget = options.renderTarget || this.renderTarget;
    },
    render: function () {
        if (this.renderTarget) {
           $(this.renderTarget).html(this.el);
        }
        ... render stuff into $(this.el) ...
        return this;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      相关资源
      最近更新 更多