1

我正在写一个Backbone App我试图呈现一个在我写一个input字段时检索到的结果列表的地方。

这基本上是我的应用程序

var Dropdown = {
    Models: {},
    Collections: {},
    Views: {},
    Templates:{}
}

Dropdown.Models.Product = Backbone.Model.extend({
    defaults: dropdown.product.defaults || {},
    initialize:function () {
        console.log('Dropdown.Models.Product > initialize');
    }
});

Dropdown.Collections.Products = Backbone.Collection.extend({
    model: Dropdown.Models.Product,
    initialize:function () {
        console.log('Dropdown.Collections.Products > initialize');

    }
});

Dropdown.Views.App = Backbone.View.extend({
    initialize:function () {
        console.log('Dropdown.Views.App > initialize');
        this.subView = {
            Product : new Dropdown.Views.Product({
                collection : new Dropdown.Collections.Products()
            })
        }
    },
    render:function (options, term) {
        console.log('Dropdown.Views.App > render');
        var defaults = {
            where:false,
            products:{
                id:"product-results"
            }
        }
        var settings = $.extend(true, defaults, options);
        this.$el.html(this.subView.Product.render(settings.products.view, term).$el);
        // this.delegateEvents();
    }
});

Dropdown.Views.Product = Backbone.View.extend({
    initialize:function () {
        console.log('Dropdown.Views.Product > initialize');
    },
    events: {
        "click .close": "closeResults",
    },
    closeResults:function (event) {
        console.log('Dropdown.Views.Product > closeResults');
        var view = this;
        this.$el.animate({height:0}, 500, function () {
            $(this).removeAttr('style');
            view.$el.hide();
        });
    },
    render:function (view, term) {
        this.$el.show();
        console.log('Dropdown.Views.Product > render');
        var data = (this.collection || this.model).toJSON();
        var template = Handlebars.compile($(this.template).html());
        this.$el.html(template({view:view, results:data}));
        this.delegateEvents(this.events); // to assign events if I'm using $el.html(...)
        return this;
    }
});

render该应用程序有效,但在调用第二种方法后我丢失了事件,可能是因为调用了该.html()方法。

第一个回调:

 ---------------------
| app widget          |
 ---------------------
| result 1            |
| result 2            |
 ---------------------
|               close | <= event closeResults works
 ---------------------

第二次回调:

 ---------------------
| app widget          |
 ---------------------
| result 1            |
| result 2            |
| result 3            |
 ---------------------
|               close | <= event closeResults lost
 ---------------------

如果我尝试将我的应用程序的方法渲染更改为:

render:function (view, term) {
    this.$el.show();
    console.log('render');
    var data = this.collection.toJSON() || this.model.toJSON();
    var template = Handlebars.compile($(this.template).html());
    // CHANGED this.$el.html to this.$el.append
    this.$el.append(template({view:view, results:data}));
    return this;
}

事件始终有效,但我将服务器响应累积到应用程序的 html 中,因此结果如下:

第一个回调:

 ---------------------
| app widget          |
 ---------------------
| result 1            |
| result 2            |
 ---------------------
|               close | <= event closeResults works
 ---------------------

第二次回调:

 ---------------------
| app widget          |
 ---------------------
| result 1            |
| result 2            |
 ---------------------
|               close | <= event closeResults works
 ---------------------
| app widget          | <= appended content, it doesn't replace previous result
 ---------------------
| result 1            |
| result 2            |
| result 3            |
 ---------------------
|               close | <= event closeResults works
 ---------------------

基本上,通过 append 我保持事件正常工作但我不替换内容,我应该如何让事件与html方法一起工作?

append我应该以某种我错过的方式继续使用并防止重复吗?

4

2 回答 2

1

您可以将delegateEvents添加到您的渲染中。

render:function (view, term) {
    this.$el.show();
    console.log('render');
    var data = this.collection.toJSON() || this.model.toJSON();
    var template = Handlebars.compile($(this.template).html());
    this.$el.html(template({view:view, results:data}));
    this.delegateEvents();
    return this;
}

这会将视图事件哈希中的所有事件重新绑定到您的 el。

于 2013-04-29T00:28:16.563 回答
0

我通过以这种方式更改.html方法解决了我的问题.append

Dropdown.Views.App = Backbone.View.extend({
render:function (options, term) {
    console.log('Dropdown.Views.App > render');
    var defaults = {
        where:false,
        products:{
            id:"product-results"
        }
    }
    var settings = $.extend(true, defaults, options);
    // NO MORE THIS this.$el.html(this.subView.Product.render(settings.products.view, term).$el);
    this.subView.Product.delegateEvents();
    this.$el.empty();
    this.$el.append(this.subView.Product.render(settings.products.view, term).$el);
}
});
Dropdown.Views.Product = Backbone.View.extend({ 
// ...
render:function (view, term) {
    this.$el.show();
    console.log('Dropdown.Views.Product > render');
    var data = (this.collection || this.model).toJSON();
    var template = Handlebars.compile($(this.template).html());
    // NO MORE THIS this.$el.html(template({view:view, results:data}));
    this.$el.empty();
    this.delegateEvents(this.events);
    this.$el.append(template({view:view, results:data}));
    // to assign events if I'm using $el.html(...)
    return this;
}
});

这样,它就起作用了。

于 2013-05-09T19:56:45.220 回答