渲染骨干模型视图返回未定义 [英] Render a View of Backbone Model returns undefined

查看:71
本文介绍了渲染骨干模型视图返回未定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说我有一个像这样的JSON:

Lets say i have a JSON like this:

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

JSON example, my json is validated on jsonlint and it works.

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

我创建了一个Collection,可以解析json的内容,并从此json生成模型和集合.

I have made a Collection that parse the contents of the json and generates model and collections from this 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, 初始化:function(){ _.bindAll(this,'render'); }, //在这里,我传递了要渲染的模板(html源代码). 渲染:功能(模板){ var html = render(template,this.model.toJSON()); App.$ main_content.html(html); 返回这个; } });

App.TemplateView = Backbone.View.extend({ el: App.$main_content, initialize: function(){ _.bindAll(this, 'render'); }, //Here i pass the template(html source) i want to render. render: function(template){ var html = render(template, this.model.toJSON() ); App.$main_content.html(html); return this; } });

还有我的start.js,它们存放着我的模型和视图的所有声明:

And my start.js where they live all the declarations of my models and views:

//应用 应用= =

//app 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({

//router 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'"

My problem is that when the html is loaded the only thing i have is: "Uncaught TypeError: Cannot call method 'toJSON' of undefined "

但是当我将其放在开发者控制台上时:

But when i put this on the developer console:

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

我的视图正确呈现.

为什么只有在将代码放在开发人员控制台上时,我的视图才不会显示在负载上?

Why my view isn't rendered on the load and only when i put my code on the developer console?

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

How can i render my model on the view on the router url? Why do i have undefined on the html loaded on the developer console?

----编辑---

好的,

我想我明白.也许我正在产生一个不一定有问题的问题.

I think i understand. Maybe I'm generating a problem of a thing that does not have to have a problem.

现在我的模型是这样的:

Now my Model is like this:

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;
    }
});

现在我可以在视图中看到我的收藏了.

Now i see my collection inside my View.

但是当我尝试执行此操作以仅在View上获取文本版本时:

But when i try to do this to get only the text version on my View:

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

我收到未定义的错误:

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

Uncaught TypeError: Cannot call method 'get' of undefined

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

Any idea about how can i resolve this?

我正在尝试自己解决这个问题.我不想看起来像我要开发解决方案.

I'm trying to solve this by myself. I do not want to look like im asking to develop my solution.

谢谢.

推荐答案

阅读起来有些困难,但快速浏览一下:您的App.texts =位于Collection的parse()函数中.结果,一旦在集合上执行了.fetch(),它就会被调用...直到那时,您的App.texts才是未定义的!

It's a little hard to read, but at a quick glance: your App.texts = is in in the parse() function of your Collection. As a result, it gets called once the .fetch() on the collection is performed... until then, your App.texts is undefined!

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

If App.texts is undefined when you create the TemplateView, then the view's model will actually be undefined, and so, in the render, when the template engine you use is doing a toJSON(), it will say that it has an undefined value...

可能还有其他问题,但这是最明显的问题.这是快速&肮脏的解决方法:完成fetch()后,您的集合将触发重置事件.这就是进行渲染的提示.因此,您可以做的是,无需将模型传递给View,而可以传递集合:

There may be other problems, but this one is the most glaring. Here is a quick&dirty fix: once the fetch() is done, your collection will trigger a reset event. That's your cue for doing the rendering. So, what you can do, is instead of passing the model to the View, you can pass the collection instead:

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

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

Now, in your View's initialize, you can do something like:

 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");
   });
 }

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

If you give a collection as a param to a View's construction, it'll be stored in this.collection, same as with model. The idea here is to use the events to know when to do the rendering, and also let the view tell you when it's ready to render. You could also do something in your render() function to check if the model is defined!

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

To see if this analysis is correct, you can put a console.log(App.texts); in your index function in the router.

使代码更明显的一种方法是直接在App的init中初始化App.texts和App.vias.如果确实需要在AppTemplates的fetch()解析中侧面加载它们,请给它们一个对您AppTemplatesCollection的引用.所不同的是,您可以绑定到App.vias集合中的事件(添加",删除",重置")或App.texts模型中的事件(更改").

One way to make the code a bit more obvious is to initialize your App.texts and App.vias directly in your App's init. And give a reference to them to your AppTemplatesCollection if you really need to side-load them in the parse of AppTemplates' fetch(). The difference that makes is that you can bind to events from the App.vias collection ('add', 'remove', 'reset') or to the App.texts model ('change').

我注意到的另一件事是,您有一个App.TemplateModel集合,但是您仍在创建App.texts,将提取结果放入您自己的App.TemplateModel实例中?这似乎不对,也许您有这样做的理由,但是在最一般的情况下,该集合被认为可以处理模型的创建,尤其是在获取之后!

Another thing I noticed is that you have a collection of App.TemplateModel but you are still creating a App.texts where you put the result of the fetch into your own instance of App.TemplateModel? That doesn't seem right, maybe you have a reason for doing so, but in the most general case, the collection is suppose to handle the creation of the models, especially after a fetch!

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

The usual use case of the parse() method is to side-load data (other models/collection), change the format (from XML to something JS can understand) or to remove useless keys (for instance user: {id: ..., name: ... }, you'll return response.user so that Backbone can play with the correct hash directly). What you are doing here seems to fall out of this pattern so maybe it's a cause for worry?

这篇关于渲染骨干模型视图返回未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆