渲染Backbone Model的视图返回undefined

时间:2013-12-02 14:27:06

标签: javascript backbone.js backbone-views backbone-collections backbone-model

假设我有一个像这样的JSON:

JSON示例,我的json在jsonlint上验证并且可以正常工作。

json_object = {
"texts_model": {
"hello": "hola",
"icon_text": "Icon!"
},
"collection_vias": {
"text": "hola",
"icon_text": "Icon!"
}
};

我创建了一个Collection来解析json的内容,并从这个json生成模型和集合。

App.TemplatesCollection = Backbone.Model.extend({

    model: App.TemplateModel,
    url: TEMPLATES_SERVICE,

    initialize: function(){
        this.fetch({
            success: (function () {
                console.log(' Success ');
            }),
            error:(function (e) {
                //console.log(' Error: ' + e);
            }),
            complete:(function (e) {
                console.log(' Fetch completado con exito. ');

            })
        });
    },

    //Here i generate all my models and collections.
    parse: function(response){

        App.texts = new App.TemplateModel(response.text_model);
        App.vias = new App.ViasCollection(response.collection_vias);
        return response;
    },

    //I was trying with the get function but i the only thing i got was undefined.
    plain_texts: function(){
        return( this.get('plain_texts') ) ;
    }

});

视图是这样的:

App.TemplateView = Backbone.View.extend({     el:App。$ main_content,     initialize:function(){         _.bindAll(this,' render');     },     //这里我传递了我要渲染的模板(html源代码)。     渲染:function(template){         var html = render(template,this.model.toJSON());         应用$ main_content.html(HTML)。         归还这个;     } });

我的start.js在那里他们生活了我的模型和视图的所有声明:

//应用 App = {

init: function(){
    console.log('Iniciando...');

    //variables y constantes
    App.$main_content       = $('#main-content-content');
    App.$main_header        = $('#main-header-content')
    App.$main_navigation    = $('#main-navigation-content');

    //data
    App.templates = new App.TemplatesCollection();

    //views
    App.templateView = new App.TemplateView({model: App.texts});

    //router
    App.router = new App.Router();


},

start: function(){
    //init
    App.init();

    //router
    Backbone.history.start();

}

}

路由器:

//路由器 App.Router = Backbone.Router.extend({

routes:{
    "" : "index",
    ":web" : "url"

},

index: function(){
    console.log("index");

    //Here i do not know what to do, i mean do i have to instiate the View each time i go to index? or only render?
    App.templateView = new App.TemplateView({model: App.texts});
    App.templateView.render("sections/login/form");
},

url: function(web){
    console.log(web);
}

});

//on document ready
$(function(){

    App.start();


});

我的问题是,当加载html时,我唯一拥有的是: "未捕获的TypeError:无法调用方法' toJSON'未定义"

但是当我把它放在开发者控制台上时:

App.templateView = new App.TemplateView({model: App.texts});
App.templateView.render("sections/login/form");

我的观点正确呈现。

为什么我的视图不会在加载时呈现,只有当我将代码放在开发者控制台上时才会显示?

如何在路由器URL上的视图上渲染我的模型? 为什么我在开发者控制台上加载的html上有未定义的内容?

---- --- EDIT

好的,

我想我明白了。也许我会产生一个没有问题的问题。

现在我的模型是这样的:

App.TemplatesCollection = Backbone.Model.extend({

    model: App.TemplateModel,
    url: TEMPLATES_SERVICE,

    plain_texts: function(){
        return this.get('texts')  ;
    },
    initialize: function(){
        this.fetch();
    }

});

观点:

App.TemplateView = Backbone.View.extend({
    el: App.$main_content,
    initialize: function(){

        console.log(this.collection);
        var ea = this.collection.get('texts');
        console.log(ea);
    },
    render: function(template){
        console.log(this.collection);
        return this;
    }
});

现在我在我的视图中看到了我的收藏。

但是,当我尝试这样做只获取我的视图上的文本版本时:

    var ea = this.collection.get('texts');
    console.log(ea);

我得到了未定义的错误:

  

未捕获的TypeError:无法调用方法' get'未定义的

关于如何解决这个问题的任何想法?

我试图自己解决这个问题。我不想看起来像是要求开发我的解决方案。

提前致谢。

2 个答案:

答案 0 :(得分:0)

这有点难以阅读,但是快速浏览一下:你的App.texts =在你的Collection的parse()函数中。结果,一旦执行了集合上的.fetch()就会调用它......直到那时,你的App.texts是未定义的!

如果在创建TemplateView时未定义App.texts,那么视图的模型实际上将是未定义的,因此,在渲染中,当您使用的模板引擎正在执行toJSON()时,它会说它具有未定义的值......

可能还有其他问题,但这个问题最明显。这是一个快速和彻底的修复:一旦fetch()完成,您的集合将触发重置事件。这是你做渲染的提示。因此,您可以做的是,不是将模型传递给View,而是可以传递集合:

 App.templateView = new App.TemplateView({collection: App.templates});

现在,在View的初始化中,您可以执行以下操作:

 if(App.texts) {
   //Your collection has already fetched and already went through parse()
   this.model = App.texts;
   this.render("sections/login/form");
 } else {
   //Your collection hasn't done the fetch yet
   view = this;
   this.collection.one("reset", function(){
     view.model = App.texts;
     view.render("sections/login/form");
   });
 }

如果您将一个集合作为View的构造的参数,它将存储在this.collection中,与模型相同。这里的想法是使用事件来知道何时进行渲染,并让视图告诉您何时可以渲染。您还可以在render()函数中执行某些操作来检查模型是否已定义!

要查看此分析是否正确,您可以放置​​console.log(App.texts);在路由器的索引函数中。

使代码更明显的一种方法是直接在App的init中初始化App.texts和App.vias。如果你真的需要在AppTemplates的fetch()的解析中加载它们,请将它们引用到你的AppTemplatesCollection。不同之处在于您可以绑定App.vias集合中的事件('add','remove','reset')或App.texts模型('change')。

我注意到的另一件事是你有一个App.TemplateModel的集合,但是你仍在创建一个App.texts,你把fetch的结果放到你自己的App.TemplateModel实例中?这似乎不对,也许你有理由这样做,但在最一般的情况下,该集合假设处理模型的创建,特别是在获取之后!

parse()方法的通常用例是侧载数据(其他模型/集合),更改格式(从XML到JS可以理解的东西)或删除无用的键(例如user:{id :...,name:...},你将返回response.user,以便Backbone可以直接使用正确的哈希)。你在这里做的事情似乎不属于这种模式,所以可能会引起担忧?

答案 1 :(得分:0)

在您的代码中,您创建了collection

App.TemplatesCollection = Backbone.Model.extend({
//rest of the code

如果您想创建collection,则需要展开{​​{1}}而不是Backbone.Collection

Backbone.Model