Backbone console.log returning collection and undefined

[亡魂溺海] 提交于 2019-12-12 03:35:58

问题


Something odd is going on with my Backbone project. I'm rebuilding it as AMD and I'm having to change some variable names to get it working again. I have a collection I'm passing into a view, but when I console.log the collection, I get both the object and null.

Here is my view:

define([
    'jquery',
    'underscore',
    'backbone',
    'models/tableModel',
    'collections/tablesCollection',
    'views/tablesView',
    'views/tableView'
],
function($, _, Backbone, tableModel, tablesCollection, tableView) {
    var tv = Backbone.View.extend({
        tagName: 'div',
        initialize: function() {
            console.log(this.collection);
            this.collection.on('reset', this.render, this);
            this.template = this.options.template;
            this.url = this.collection.url;

        },
        render: function() {
            //tablesCollection.collection.each(this.addOne, this);
            return this;
        },
        addOne: function(model) {
            var t = new tableView({ model: model, template: this.template, url: this.url });
            this.$el.append(t.render().el);
            return this;
        },
        stripQueryString: function(url) {
            return url.split('?')[0];
        }
    });

    return tv;
});

You'll see the console.log several lines down in the project. Here is what I get in Firebug as a result:

Both cite the same line number. Here is what's in the object:

What is going on here? Why am I getting two results for the same thing? One of them is what I want and the other one isn't.

EDIT: Here is where I instantiate the view:

define([
    'jquery',
    'underscore',
    'backbone',
    'models/tableModel',
    'collections/TablesCollection',
    'views/tablesView',
    'views/tableView'
], function($, _, Backbone, TableModel, tablesCollection, tablesView, tableView) {
    var t = new tablesCollection(null, { url: 'main-contact'} );
    var tables = new tablesView({ collection: t, template: 'main-contact-template'});
    $('#web-leads').html(tables.render().el);

});

Here is my collection:

define([
    'jquery',
    'underscore',
    'backbone',
    'models/tableModel'
],
function($, _, Backbone, tableModel) {
    var tablesCollection = Backbone.Collection.extend({
        url: this.url,
        model: tableModel,
        initialize: function(models, options) {
            if (options && options.url) {
                this.url = options.url;
            }
            this.fetch({
                success: function(data, options) {

                }
            });
        }
    });

    return tablesCollection;
});

Two other files:

// Filename: app.js
define([
    'jquery',
    'underscore',
    'backbone',
    'router' // Request router.js
], function($, _, Backbone, Router){
    var initialize = function(){
    // Pass in our Router module and call it's initialize function
    Router.initialize();
};

return {
    //initialize: initialize  <--This is where the second init call was happening.
};
});

Main.js:

 require.config({
        paths: {
            //jquery: 'libs/jquery/jquery-1.8.3.min',
            underscore: 'libs/underscore/underscore-min',
            backbone: 'libs/backbone/backbone-min'
        }
    });

    if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
      define( 'jquery', [], function () { return jQuery; } );
    }

    //the "main" function to bootstrap your code
    require(['jquery', 'underscore', 'backbone', 'app'],
        function () {
            var App = require('app');
            App.initialize();
            // console.log($);
            // console.log(_);
            // console.log(Backbone);
    });

回答1:


You prior version of the code made more sense than this edited version, as in the prior version you were actually pushing to console.log the object that was giving trouble

// contents of 'that/view/that/gives/me/problems.js'
define([
    'jquery',
    'underscore',
    'backbone',
    'models/tableModel',
    'collections/tablesCollection',
    'views/tablesView',
    'views/tableView'
],
function($, _, Backbone, tableModel, tablesCollection, tableView) {
    console.log("factory", tablesCollection.collection); // <- you did not have this line. my addition
    var tv = Backbone.View.extend({
        tagName: 'div',
        initialize: function() {
            console.log("init", tablesCollection.collection); // <- your prior version. Point of your error
            this.collection.on('reset', this.render, this);
            this.template = this.options.template;
            this.url = this.collection.url;

        }
        // ...
    });

    return tv;
});

Now the reason you have it show up twice is because the view you define above is initialized twice somewhere.

First time it's initialized it shows the value as you can see. The second time around the pointer tablesCollection is cleaned up by something and, hence, you have that error.

Now what cleans up tablesCollection and why I don't see anywhere in the code you present. It has likely something to do with re-requiring 'collections/tablesCollection' module somewhere in your code. As I can see from your 'collections/tablesCollection' module code, you REDEFINE the output on every factory call. What I would do is calc it once and serve cached:

// contents of 'collections/tablesCollection.js'
;(function(){

    var mythings = {}

    function initializer($, _, Backbone, tableModel){
        return Backbone.Collection.extend({
            url: 'url',
            model: tableModel,
            initialize: function(models, options) {
                // ...
            }
        });
    }

    define([
        'jquery',
        'underscore',
        'backbone',
        'models/tableModel'
    ],
    function($, _, Backbone, tableModel) {
        if (!mythings.tablesCollection){
            // this will be done on first run.
            mythings.tablesCollection = initializer($, _, Backbone, tableModel)
        }
        // all others will just return same exact instance of collection class
        return mythings.tablesCollection
    })

})();

EDIT:

Asked the AMD spec group if there is a chance of 'factory' function rerunning on every require. Immediate answer was "Not likely" but long term answer is "Possible (if asked under different name)"

I added comment lines to the code snippet above indicating what files they are.

I also added a console.log line in the first snippet that should help you understand that the issue you have is NOT with AMD loader. You simply initialize the view twice somewhere.

When you run the code with comment lines like in the top snippet you will see factory log line shoing up only once and init line twice, like in your origianl error screenshot.

You need to trace where you use the view returned in that tv variable. You are initing it twice.

As to what happens to (what clears) reference to tablesCollection in the second run I don't know and don't see anywhere in the snippets you provided.



来源:https://stackoverflow.com/questions/14512551/backbone-console-log-returning-collection-and-undefined

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!