简体   繁体   English

骨干列表视图/渲染列表视图项目

[英]Backbone List View / Rendering List View Items

I am pretty new to Backbone.js. 我对Backbone.js很陌生。 Please see my code for what I reference here. 请参阅我的代码以获取此处引用的内容。 I have a View that is supposed to show a Collection of 'Stock' Models. 我有一个视图,该视图应该显示“股票”模型的集合。 This View is called 'StockDashboardView'. 该视图称为“ StockDashboardView”。 Each of the Stock Models that this View needs to can be shown with the 'StockDashboardItemView'. 此视图所需的每种股票模型都可以与“ StockDashboardItemView”一起显示。 Before each StockDashboardItemView renders though, it's respective Stock Model needs to fetch some data (make a request for stock prices) so that the StockDashboardItemView can use the data to draw a graph. 但是,在每个StockDashboardItemView呈现之前,需要分别的股票模型获取一些数据(请求股票价格),以便StockDashboardItemView可以使用该数据绘制图形。 The StockDashboardView loops through each of the Stock Models and creates a StockDashboardItemView for each one. StockDashboardView遍历每个股票模型,并为每个模型创建一个StockDashboardItemView。 I should be getting 5 different graphs with different company datapoints in each. 我应该得到5个不同的图形,每个图形中都有不同的公司数据点。 But all the graphs are the same, which means each of the 5 StockDashboardItemViews has the same model somehow. 但是所有图形都是相同的,这意味着5个StockDashboardItemViews中的每一个都具有相同的模型。 I know my fetch/looping logic is wrong but I don't know how or why. 我知道我的提取/循环逻辑是错误的,但我不知道如何或为什么。 I also tried fetching in the individual StockDashboardItemViews instead of the StockDashboardView (see commented out code). 我还尝试在单个StockDashboardItemViews中而不是在StockDashboardView中进行获取(请参阅注释掉的代码)。 Looking in my console.log statements I see the following print statements: (the collection has 5 models). 在console.log语句中查看以下打印语句:(该集合有5个模型)。 Could someone please help me fix my logic? 有人可以帮我纠正我的逻辑吗? Thank you 谢谢

----------1-------- ---------- 1 --------

----------1-------- ---------- 1 --------

----------1-------- ---------- 1 --------

----------1-------- ---------- 1 --------

----------1-------- ---------- 1 --------

----------2-------- ---------- 2 --------

----------3-------- ---------- 3 --------

----------2-------- ---------- 2 --------

----------3-------- ---------- 3 --------

----------2-------- ---------- 2 --------

----------3-------- ---------- 3 --------

----------2-------- ---------- 2 --------

----------3-------- ---------- 3 --------

----------2-------- ---------- 2 --------

----------3-------- ---------- 3 --------

            window.StockDashboardView = Backbone.View.extend({

                initialize: function () {
                    this.render();
                },

                render: function () {
                    var stocks = this.model.models;
                    var len = stocks.length;
                    var startPos = (this.options.page - 1) * 8;
                    var endPos = Math.min(startPos + 8, len);

                    $(this.el).html('<ul class="thumbnails"></ul>');
                    for (var i = startPos; i < endPos; i++) {
                        console.log("----------1--------");
                        var stock = stocks[i];
                        stock.set("_id", stocks[i].toJSON()["tickerSymbol"]);
                        stock.fetch({success: function(model, response, options){
                            stock.set("data", response);
                            // set interactivity to false
                            console.log("-----------2---------");
                            $('.thumbnails', this.el).append(new StockDashboardItemView({model: stock}).render().el);
                        }});

                    }

                    $(this.el).append(new Paginator({model: this.model, page: this.options.page}).render().el);

                    return this;
                }
            });

            window.StockDashboardItemView = Backbone.View.extend({

                tagName: "li",

                initialize: function () {
                    this.model.bind("change", this.render, this);
                    this.model.bind("destroy", this.close, this);
                },

                render: function () {
                    $(this.el).html(this.template(this.model.toJSON()));
                    var context = this.$("#chart_div")[0];
                    var stock = this.model;
                    stock.set("_id", stock.toJSON()["tickerSymbol"]);
                    //stock.fetch({success: function(model, response, options){
                        //stock.set("data", response);
                        // set interactivity to false
                        console.log("-----------3---------");
                        var chart = new TFChart(stock.get("_id"), stock.attributes['data'], context, false, this.$("#chart_div").width(), this.$("#chart_div").height());
                        return this;
                    //}});     
                }
            });

In your for-loop , you use stock = stocks[i] to get each of the stock, then fetch them. for-loop ,您使用stock = stocks[i]来获取每张股票,然后取回它们。

However, as .fetch is async method, when it starts to execute to render a view for stock, you'll notice that the stock is now point to the last item in the stocks, so it just render the last item for many times. 但是,由于.fetchasync方法,当它开始执行以呈现库存视图时,您会注意到库存现在指向库存中的最后一项,因此它多次渲染最后一项。

Why this happens? 为什么会这样? Because the var use function scope, not block scope(In ES6, there's a let can use block scope, but is a little off-topic here), so all of the .fetch 's success callback, when they want to use stock , they all see the same stock , which would be the last assigned value in for-loop, and should be the last item of stocks. 因为var使用函数作用域,而不是块作用域(在ES6中,有一个let可以使用块作用域,但是这里有点偏离主题了),因此,当他们想要使用stock ,所有.fetch的成功回调,他们都看到相同的stock ,这将是for循环中最后分配的值,并且应该是库存的最后一项。

It's a scope issue, and the solution is to wrap the context to a function, so the function's scope will keep the item for you: 这是一个范围问题,解决方案是将上下文包装到一个函数中,因此该函数的范围将为您保留该项目:

render: function () {
    var stocks = this.model.models;
    var len = stocks.length;
    var startPos = (this.options.page - 1) * 8;
    var endPos = Math.min(startPos + 8, len);

    // Move this.el to here, so the this.el's this won't be a problem.
    var thisEl = this.el;
    var fetchStock = function(stock) {
        stock.set("_id", stocks[i].toJSON()["tickerSymbol"]);
        stock.fetch({success: function(model, response, options){
            stock.set("data", response);
            // set interactivity to false
            console.log("-----------2---------");
            $('.thumbnails', thisEl).append(new StockDashboardItemView({model: stock}).render().el);
        }});
    };

    $(this.el).html('<ul class="thumbnails"></ul>');
    for (var i = startPos; i < endPos; i++) {
        console.log("----------1--------");
        fetchStock(stocks[i]);
    }

    $(this.el).append(new Paginator({model: this.model, page: this.options.page}).render().el);

    return this;
}

As you can see, now when we call fetchStock , it's stock will reference to the current stocks[i] , and that won't be affect by the loop after it. 如您所见,现在当我们调用fetchStock ,它的stock将引用当前的stocks[i] ,并且不会受到其后的循环的影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM