Backbone 视图扩展?

Backbone View extending?

我正在尝试创建一些组合框,它们的数据是从服务器获取的。 它们都是一样的,但数据不同。这是我的 MainView 的渲染函数:

render: function () {

        ...

        this.$el.append(this.template(this.options));


        this.$('#Type').append(new App.Views.TicketTypes({ collection : new App.Models.TicketTypes() }).render().el);

        this.$('#Priority').append(new App.Views.Priorities({ collection : new App.Models.Priorities() }).render().el);

        this.$('#Status').append(new App.Views.Statuses({ collection : new App.Models.Statuses() }).render().el);

        this.$('#State').append(new App.Views.States({ collection : new App.Models.States() }).render().el);


        return this;
    }

这是主模板:

<label class="text-center">{{Type}}</label>
                    <br>
                    <div id="Type" class="form-group">

                    </div>
                    <label class="text-center">{{Priority}}</label>
                    <br>
                    <div id="Priority">

                    </div>
                    <label class="text-center">{{Status}}</label>
                    <br>
                    <div id="Status">

                    </div>
                    <label class="text-center">{{State}}</label>
                    <br>
                    <div id="State">

                    </div>
                    <br>

这是我定义的视图:

App.Views.SelectList = Backbone.View.extend({
    template: templates.SelectList,
    collection : null,
    initialize: function (options) {
        if (options) {
            this.collection = options.collection;
        }
    },
    render: function () {
        this.el.innerHTML = this.template(this.options);
        thiz = this;
        this.collection.fetch({beforeSend :App.Auth , success : function (collection , response) {
            collection.each(function (item) {
                thiz.$('select').append("<option>" + item.get('Text') + "</option>");
                    } , this);
        }});

        return this;
    }
});

App.Views.TicketTypes = App.Views.SelectList.extend();
App.Views.Priorities = App.Views.SelectList.extend();
App.Views.Statuses = App.Views.SelectList.extend();
App.Views.States = App.Views.SelectList.extend();

这是选择列表模板:

<select class="form-control">

</select>
<br>

我所有的模特都是这样的:

{"id":1,"Text":"Netowrk"}

但这就是我从服务器得到的:

正如你所看到的,只有最后一个有数据,令人惊讶的是所有模型的所有数据都进入了最后一个。看这里:

我知道我是否更改此渲染函数:

render: function () {
            this.el.innerHTML = this.template(this.options);
            thiz = this;
            this.collection.fetch({beforeSend :App.Auth , success : function (collection , response) {
                collection.each(function (item) {
                    thiz.$('select').append("<option>" + item.get('Text') + "</option>");
                        } , this);
            }});

            return this;
        }

对此:

render: function () {
        this.el.innerHTML = this.template(this.options);
        this.collection.thiz = this;
        this.collection.fetch({beforeSend :App.Auth , success : function (collection , response) {
            collection.each(function (item) {
                collection.thiz.$('select').append("<option>" + item.get('Text') + "</option>");
                    } , this);
        }});

        return this;
    }

它会解决这个问题,但是有没有更好的方法呢?

谢谢。

您遇到了范围界定问题。这个:

thiz = this;

创建一个全局 thiz 变量,因此集合迭代中的每个匿名函数:

collection.each(function (item) {
    thiz.$('select').append("<option>" + item.get('Text') + "</option>");
} , this);

最终使用完全相同的 thiz。这些 collection.each 调用包含在 AJAX 调用 (this.collection.fetch) 中,而 JavaScript 是单线程的,因此它们都将在第一个执行之前创建。这意味着所有这些函数都将使用完全相同的 thiz 并且其值将是分配给它的最后一个 thiz = this 。这是变相的经典闭包问题。

当您切换到:

this.collection.thiz = this;

您将 thiz 范围限定到正确的视图,一切都按预期工作。

正确的解决方案是使用 var or let:

正确声明 thiz
var thiz = this;
// or
let thiz = this;

检查链接的文档以了解差异。