本文介绍了Underscore.js 模板问题 - 无法调用 null 的方法“替换"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我一直在寻找并找到了很多答案,但似乎都没有.

第一;

创建方法的新实例

 var newPhoto = new Photo();newPhoto.setTitle('钓鱼');

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

newPhoto.setTitle('航行');

我收到错误 - 无法调用 null 的方法‘替换’"

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

var template = _.template($('#rtemp').html(), {title:name});
解决方案

你在这里有一些错误.

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

  2. 你的视图的 render 引用了 myPhoto 而它应该是 this.model:

    var name = this.model.get('title');

  3. 你的主要问题是你的视图使用 作为它的 this.el 而你的模板在 .

您在渲染视图时完全替换了 的内容:

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

所以在第一个 render 调用之后,没有更多的 #rtemp.然后,在下一个 render 调用中,你试试这个:

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

但是由于 #rtemp 不再在 DOM 中,所以一切都分崩离析了.

如果您立即抓取模板:

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

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

render: function(event) {//...var 模板 = this.template({标题:姓名});//...}

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

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

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

您的模型应该更像这样:

var Photo = Backbone.Model.extend({设置标题:功能(新标题){this.set({ title: newTitle });},设置位置:函数(newLoc){this.set({ location: newLoc });}});

然后你的观点是这样的:

var PhotoView = Backbone.View.extend({el: $('body'),模板:_.template($('#rtemp').html()),初始化:函数(){_.bindAll(this, 'render');this.model.on('change:title', this.render);},渲染:函数(事件){这个.$el.html(this.template(this.model.toJSON()));返回这个;}});

_.bindAlldocumentcloud.github.com/backbone/#View-constructor" rel="nofollow">initialize 确保 this.render 将使用正确的 ;然后 initialize 绑定到事件,以便它可以响应模型中的更改.视图知道它关心什么,所以它负责处理模型中的变化.在 render 中,您通常只需调用 toJSON 来获取模板的数据.此外,较新版本的 Backbone 在视图中包含缓存版本的 $(this.el) 作为 this.$el 这样你就不必再$(this.el)自己了.

然后你会像这样:

var newPhoto = new Photo();var viewPhoto = new PhotoView({ 模型:newPhoto });newPhoto.setTitle('钓鱼');newPhoto.setTitle('航行');

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

您可能还想将模板 中移出.

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

I have been looking over and found alot of answers but none seem to work.

<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>

First;

Create a new instance of the method

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

This work fine, it will load into the body via the template. However if i then do it again,

newPhoto.setTitle('Sailing');

I get the error - "Cannot call method 'replace' of null"

No line error but I believe it is at

var template = _.template($('#rtemp').html(), {title:name});
解决方案

You have a few things wrong here.

  1. Your template has a double " in the type attribute, it should be:

    <script id="rtemp" type="text/x-underscore-template">
    

  2. Your view's render is referencing myPhoto when it should be this.model:

    var name = this.model.get('title');
    

  3. And your main problem is that your view uses <body> as its this.el and your template is inside <body>.

You completely replace the content of <body> when you render your view:

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

so after the first render call, there is no more #rtemp. Then, on the next render call, you try this:

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

but since #rtemp isn't in the DOM anymore, everything falls apart.

If you grab the template immediately:

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

and then use this.template() in render:

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

you'll have better luck. You will, of course, need to make sure that you define your view inside a document-ready handler with this approach or #rtemp might not be available when you define your view.

Demo: http://jsfiddle.net/ambiguous/dwGsM/


That said, the structure of your application is rather bizarre. You have a model which listens to itself and then the model creates and renders a view when something changes. A model listening to itself is fine in itself but usually you have views listening to models and the view would re-render itself (or just parts of itself) as the model changes.

Your model should look more like this:

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

And then your view like this:

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

The _.bindAll in initialize ensures that this.render will be called with the right this; then initialize binds to the event so that it can respond to changes in the model. The view knows what it cares about so it is responsible for dealing with changes in the model. And in the render, you usually just call toJSON to get the data for the template. Also, newer versions of Backbone include a cached version of $(this.el) in the view as this.$el so you don't have to $(this.el) yourself anymore.

Then you'd crank things up like this:

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

You tell the view what model to use by specifying the model option when creating the view.

You might also want to move the template <script> out of <body>.

New and Improved Demo: http://jsfiddle.net/ambiguous/Kytw7/

这篇关于Underscore.js 模板问题 - 无法调用 null 的方法“替换"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-06 13:49