3

我一直在寻找并找到很多答案,但似乎没有一个有效。

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>
           Shopping Cart
        </title>
        <link rel="stylesheet" href="lib/style.css" type="text/css">
    </head>
    <body>
<script id="rtemp" type="text/x-underscore-template"">
            <span><%= title %></span>
    </script>
        <script src="lib/jquery.js" type="text/javascript"></script>
        <script src="lib/underscore.js" type="text/javascript"></script>
        <script src="lib/backbone.js" type="text/javascript"></script>
        <script src="lib/script.js" type="text/javascript"></script>
    </body>
    <script>
var Photo = Backbone.Model.extend({


    initialize: function(){
        console.log('this model has been initialized');

        this.bind("change:title", function(){
            var title = this.get("title");
            console.log("My title has been changed to.. " + title);
            var pv = new PhotoView();
            pv.render();
        });

    },

    setTitle: function(newTitle){
        this.set({ title: newTitle });
    },

    setLocation: function(newLoc)
    {
        this.set({location:newLoc});
    }
});

var PhotoView = Backbone.View.extend
({
    el: $('body'),

    render: function(event)
    {
        var name = myPhoto.get('title');
        console.info(name);
        var template = _.template($('#rtemp').html(), {title:name});
        console.info(this.model);
        $(this.el).html(template);
        return this;
    }

});



    </script>
</html>

第一的;

创建方法的新实例

 var newPhoto = new Photo();
 newPhoto.setTitle('Fishing');

这工作正常,它将通过模板加载到正文中。但是,如果我再做一次,

newPhoto.setTitle('Sailing');

我收到错误消息 - “无法调用 null 的方法‘替换’”

没有线路错误,但我相信它在

var template = _.template($('#rtemp').html(), {title:name});
4

1 回答 1

24

你这里有一些问题。

  1. "您的模板在属性中有一个 double type,它应该是:

    <script id="rtemp" type="text/x-underscore-template">
    
  2. 您的视图应该在什么时候render引用:myPhotothis.model

    var name = this.model.get('title');
    
  3. 而您的主要问题是您的视图<body>用作它this.el并且您的模板在里面<body>

您完全替换了<body>渲染视图时的内容:

$(this.el).html(template);

所以在第一次render调用之后,就没有了#rtemp。然后,在下一次render通话中,你试试这个:

var template = _.template($('#rtemp').html(), ...);

但由于#rtemp不再在 DOM 中,所以一切都崩溃了。

如果您立即抓取模板:

var PhotoView = Backbone.View.extend({
    el: $('body'),
    template: _.template($('#rtemp').html()),
    //...
});

然后this.template()在中使用render

render: function(event) {
    //...
    var template = this.template({
        title: name
    });
    //...
}

你会有更好的运气。当然,您需要确保使用这种方法在文档就绪处理程序中定义视图,或者#rtemp在定义视图时可能不可用。

演示:http: //jsfiddle.net/ambiguous/dwGsM/


也就是说,您的应用程序的结构相当奇怪。你有一个模型,它会倾听自己的声音,然后模型会在发生变化时创建并呈现一个视图。监听自身的模型本身很好,但通常您有监听模型的视图,并且视图会随着模型的变化重新呈现自己(或只是自身的一部分)。

你的模型应该看起来更像这样:

var Photo = Backbone.Model.extend({
    setTitle: function(newTitle) {
        this.set({ title: newTitle });
    },
    setLocation: function(newLoc) {
        this.set({ location: newLoc });
    }
});

然后你的观点是这样的:

var PhotoView = Backbone.View.extend({
    el: $('body'),
    template: _.template($('#rtemp').html()),
    initialize: function() {
        _.bindAll(this, 'render');
        this.model.on('change:title', this.render);
    },
    render: function(event) {
        this.$el.html(
            this.template(this.model.toJSON())
        );
        return this;
    }
});

_.bindAllininitialize确保将this.render被正确调用this;然后initialize绑定到事件,以便它可以响应模型中的更改。视图知道它关心什么,因此它负责处理模型中的变化。而在 中render,您通常只需调用toJSON即可获取模板的数据。此外,较新版本的 Backbone$(this.el)在视图中包含缓存版本,this.$el因此您不再需要$(this.el)自己处理。

然后你会像这样把事情搞砸:

var newPhoto = new Photo();
var viewPhoto = new PhotoView({ model: newPhoto });
newPhoto.setTitle('Fishing');
newPhoto.setTitle('Sailing');

model您可以通过在创建视图时指定选项来告诉视图使用什么模型。

您可能还想将模板<script>移出<body>.

新的和改进的演示:http: //jsfiddle.net/ambiguous/Kytw7/

于 2012-06-12T18:50:50.370 回答