Backbone.js模型默认和解析

And*_*cia 4 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;
    }
});
Run Code Online (Sandbox Code Playgroud)

哪个被送到这个模板:

<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>
Run Code Online (Sandbox Code Playgroud)

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

Uncaught TypeError: Cannot read property 'smallThumbnail' of undefined.
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过与检查修复它ifModeltemplate但有什么目的defaults模型属性呢?这是否只有在没有超越的情况下才有效parse

Ada*_*mKG 10

一些东西.首先,您通常不应该将嵌套对象作为主干模型属性 - 如果您可以始终以原子方式处理该属性,则可以是正常的,但这是一个完美的例子.从数据模型的角度来看,imageLinks应该是它自己的骨干模型类,就像volumeInfo一样.

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

defaults: function(){
    return {
        volumeInfo : {} // should be new VolumeInfo({}) imo
    };
},
Run Code Online (Sandbox Code Playgroud)

但是数据模型是一个更大的问题 - .defaults没有做你想要的那种嵌套对象模板的东西,并且有充分的理由:它不能很好地工作,这只是第一个如果你不保持你的实例数据非常平坦,你会遇到很多陷阱.

  • 除了这不是一个子对象:它是具有状态,行为或其他东西的相关模型 - 它是一个*东西*,它负责缩略图网址.尝试将数据逐字地从外部API映射到您的数据类型似乎也不是一个好主意.实际上,这就是为什么存在解析方法的原因:Google关于如何构建数据的选择可能与您的相同,也可能不同,如果不存在,解析就是转换的位置.设置从外部数据部分合并的模板对象树是...边缘情况下至少可以说. (2认同)
  • 教程示例使用本机javascript文字作为默认值:id 1,名称"Thomas"等.在这种情况下,可以不使用默认值函数.但是你有一个容器类型作为你的一个默认值; 您在实例化时为所有在attrs中没有它的实例共享相同的volumeInfo对象.共享名称:"托马斯"不是问题,因为你不能改变"托马斯",只设置一个新的字符串.你*可以*改变volumeInfo ['title'],而没有意识到它与没有明确设置的所有实例的volumeInfo相同. (2认同)