使用下划线外部模板在后骨中设置模型内容

时间:2014-04-29 12:30:42

标签: javascript templates backbone.js underscore.js

这是我的主干代码,我使用下划线模板,现在工作正常我正在尝试将该模板外部并从那里加载

这是我的示例骨干代码

              骨干应用程序                            

<div class="list"></div>

<script id="personTemplate" type="text/template">
    <strong><%= name %></strong> (<%= age %>) - <%= occupation %>
</script>
<script type="text/javascript">
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
   tagName: 'li',

    template: _.template( $('#personTemplate').html()),

    initialize: function(){
        this.render();
    },

    render: function(){
        this.$el.html( this.template(this.model.toJSON()));
    }
});
var person = new Person;  // a person object created...
//person.set('name', 'abhi');
var personView = new PersonView({ model: person });
personView.el   // ---->; You can call this method and it will display the view..
$(document.body).html(personView.el);
</script>
</body>
</html> 

真正需要的是我将此模板<strong><%= name %></strong> (<%= age %>) - <%= occupation %>放在外部文件中。我不太了解它的扩展,我认为它可以是一个html文件,并从那里加载模板,我研究它,并找到一些示例代码,并尝试了这样的事情

<script type="text/javascript">
_.mixin({templateFromUrl: function (url, data, settings) {
    var templateHtml = "";
    this.cache = this.cache || {};

    if (this.cache[url]) {
        templateHtml = this.cache[url];
        alert(templateHtml);
    } else {
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            success: function(data) {
                templateHtml = data;
                alert(templateHtml);
            }
        });

        this.cache[url] = templateHtml;
    }

    return _.template(templateHtml, data, settings);
}});
var Person = Backbone.Model.extend({
    defaults: {
        name: 'Guest User',
        age: 23,
        occupation: 'worker'
    }
});

var PersonView = Backbone.View.extend({
   tagName: 'li',

   template:_.templateFromUrl("templatefile1.html", {"name": "value","age":10}) ,
   // template:_.templateFromUrl("templatefile1.html", this.model.toJSON()) ,
  //template: _.template( $('#personTemplate').html()),
    initialize: function(){
        this.render();
    },

    render: function(){
    alert(this.template);
        this.$el.html( this.template);
    }
});
var person = new Person;  // a person object created...
//person.set('name', 'abhi');
var personView = new PersonView({ model: person });
personView.el   // ---->; You can call this method and it will display the view..
$(document.body).html(personView.el);
</script>

但是当我打电话给teemplate时template:_.templateFromUrl("templatefile1.html", {"name": "value","age":10}) , 这是工作 但是当我试图将传递模型传递给那个模板时

模板:_.templateFromUrl(&#34; templatefile1.html&#34;,this.model.toJSON())

我得到了像

这样的例外
Uncaught TypeError: Cannot read property 'toJSON' of undefined 

我该如何解决这个问题

2 个答案:

答案 0 :(得分:1)

你说的是这样的话:

var PersonView = Backbone.View.extend({
    //...
    template: _.templateFromUrl("templatefile1.html", this.model.toJSON()),
    //...
});

您认为this在这种背景下是什么?它当然不会成为你观点的一个实例,因为还没有实例。 this将在window级别,而window将无法获得有用的model属性。您需要推迟该调用,直到您使用model属性创建视图实例。

你可以使template成为一种方法:

template: function() {
    return _.templateFromUrl('templatefile1.html', this.model.toJSON());
}

然后在适当的时候调用它:

render: function(){
    this.$el.html(this.template());
    return this; // <----- Standard practise so you can x.append(v.render().el)
}

我建议不要将async:false$.ajax一起使用,这对人们来说是件令人讨厌的事情。相反,你应该递交templateFromUrl一个回调函数,它可以在模板从服务器进入时调用。

如果您要做很​​多这样的事情,那么您可以在基本视图中添加template函数:

var BaseView = Backbone.View.extend({
    template: function() {
        // This assumes that you have exactly one of `this.model` and
        // `this.collection`, you can do other things here if that doesn't
        // work in your world.
        var data_source = this.model || this.collection;
        return _.templateFromUrl(this.template_name, data_source.toJSON());
    }
});

然后使用您的PersonView

var PersonView = BaseView.extend({
    template_name: 'templatefile1.html',
    render: function() {
        this.$el.html(this.template());
        return this;
    },
    //...
});

答案 1 :(得分:0)

您需要使模型可重用,并定义网址:

 var PersonModel = Backbone.Model.extend({
    defaults: {
        name: 'Untitled',
        age: 0,
        occupation: null,
    },
    url: "/somefile.json"
});

为视图内的模型更改创建一个侦听器,并获取模型:

    initialize: function(options){
        this.listenTo(this.model, "change", this.render);
        this.model.fetch();
    }

创建一个新模型,然后将其传递给新视图:

var person = new PersonModel();
var personView = new PersonView({ model: person });