Backbone.js模型的默认设置和解析 [英] Backbone.js Model defaults and parse

查看:75
本文介绍了Backbone.js模型的默认设置和解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个Backbone.Model代表Google Books API卷:

    var Book = Backbone.Model.extend({

    defaults: {
        volumeInfo : {
            title: 'n.a.',
            authors: 'n.a.',
            publisher: 'n.a.',
            publishedDate: 'n.a.',
            imageLinks : {
                smallThumbnail: '/unavailable.jpg'
            }
        }
    },

    parse: function(resp) {
        if (resp.volumeInfo.authors) {
            resp.volumeInfo.authors = resp.volumeInfo.authors.join(',');
        }
        return resp;
    }
});

将哪个模板供稿:

<script type="text/template" id="bookCollectionRow">
    <tr>
        <td><img class="thumbnail" src="<%= volumeInfo.imageLinks.smallThumbnail %>" /></td>
        <td><a target="_blank" href="<%= volumeInfo.canonicalVolumeLink %>"><%= volumeInfo.title %></a></td>
        <td><%= volumeInfo.authors %></td>
        <td><%= volumeInfo.publisher %></td>
        <td><%= volumeInfo.publishedDate %></td>
    </tr>
</script>

在解析模板时,当卷JSON不包含imageLinks时,我会收到此错误:

Uncaught TypeError: Cannot read property 'smallThumbnail' of undefined.

我知道我可以通过在Modeltemplate中使用if检查来修复它,但是defaults模型属性的目的是什么?仅在不覆盖parse的情况下才有效吗?

解决方案

一些事情.首先,一般来说,您不应将嵌套对象作为主干模型属性-如果您始终可以原子地对待该属性,则可以,但是这是您不能做到这一点的完美示例.从数据模型的角度来看,imageLinks应该是它的 own 骨干模型类,而volumeInfo也应该是它.

第二,如果默认值是对象文字({})而不是函数,则将同一对象用作每个模型实例的默认属性.我想你想要这个:

defaults: function(){
    return {
        volumeInfo : {} // should be new VolumeInfo({}) imo
    };
},

但是数据模型是一个更大的问题-.defaults不会执行您似乎想要的那种嵌套对象模板的事情,并且有充分的理由:它不能很好地工作,这只会如果不保持实例数据的平稳性,就会遇到很多陷阱中的第一个.

I've got this Backbone.Model representing a Google Books API volume:

    var Book = Backbone.Model.extend({

    defaults: {
        volumeInfo : {
            title: 'n.a.',
            authors: 'n.a.',
            publisher: 'n.a.',
            publishedDate: 'n.a.',
            imageLinks : {
                smallThumbnail: '/unavailable.jpg'
            }
        }
    },

    parse: function(resp) {
        if (resp.volumeInfo.authors) {
            resp.volumeInfo.authors = resp.volumeInfo.authors.join(',');
        }
        return resp;
    }
});

Which is fed to this template:

<script type="text/template" id="bookCollectionRow">
    <tr>
        <td><img class="thumbnail" src="<%= volumeInfo.imageLinks.smallThumbnail %>" /></td>
        <td><a target="_blank" href="<%= volumeInfo.canonicalVolumeLink %>"><%= volumeInfo.title %></a></td>
        <td><%= volumeInfo.authors %></td>
        <td><%= volumeInfo.publisher %></td>
        <td><%= volumeInfo.publishedDate %></td>
    </tr>
</script>

Upon parsing the template, when a volume JSON does not contain an imageLinks I receive this error:

Uncaught TypeError: Cannot read property 'smallThumbnail' of undefined.

I know I could fix it by checking with an if in the Model or in the template but what's the purpose of defaults model property then? Does that work only if not overriding parse?

解决方案

A few things. First, you shouldn't have nested objects as backbone model attributes in general - it can be OK if you can always treat the attribute atomically, but this is a perfect example of when you can't. From a data-model perspective, imageLinks should be its own backbone model class, as should volumeInfo.

Second, if defaults is an object literal ({}) instead of a function, the same object is used as the default attrs for each model instance. I think you want this:

defaults: function(){
    return {
        volumeInfo : {} // should be new VolumeInfo({}) imo
    };
},

But the data model is the bigger issue - .defaults doesn't do the kind of nested-object-template thing you seem to be going for, and for good reason: it doesn't work well, this will just be the first of many gotchas you'll run into if you don't keep your instance data pretty flat.

这篇关于Backbone.js模型的默认设置和解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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