2016-10-29 33 views
0

我正在編寫我的第一個Backbone博客應用程序,但是當我嘗試添加新帖子時,它會引發錯誤。id未在child.eval處定義

這裏是我的app.js(骨幹所有相關組件都在這個文件):

_.templateSettings = { 
    interpolate: /\{\{(.+?)\}\}/g 
}; 

var Post = Backbone.Model.extend({}); 
var Posts = Backbone.Collection.extend({ 
    model : Post, 
    url : "/posts" 
}); 

var PostListView = Backbone.View.extend({ 
    tagName: "li", 
    template: _.template("<a href='/posts/{{id}}'>{{title}}</a>"), 
    events: { 
     'click a': 'handleClick' 
    }, 
    handleClick: function (e) { 
     e.preventDefault(); 
     postRouter.navigate($(e.currentTarget).attr("href"), 
      {trigger: true}); 
    }, 
    render: function() { 
     this.el.innerHTML = this.template(this.model.toJSON()); 
     return this; 
    } 
}); 

var PostsListView = Backbone.View.extend({ 
    template: _.template("<h1>My Blog</h1><a href='/post/new' class='newPost'>New</a> <ul></ul>"), 
    events: { 
     'click .newPost': 'handleNewClick' 
    }, 
    handleNewClick: function (e) { 
     e.preventDefault(); 
     postRouter.navigate($(e.currentTarget).attr("href"), 
      {trigger: true}); 
    }, 
    render: function() { 
     this.el.innerHTML = this.template(); 
     var ul = this.$el.find("ul"); 
     this.collection.forEach(function (post) { 
      ul.append(new PostListView({ 
       model: post 
      }).render().el); 
     }); 
     return this; 
    } 
}); 

var PostView = Backbone.View.extend({ 
    template: _.template($("#postView").html()), 
    events: { 
     'click a': 'handleClick' 
    }, 
    render: function() { 
     var model = this.model.toJSON(); 
     model.pubDate = new Date(Date.parse(model.pubDate)).toDateString(); 
     this.el.innerHTML = this.template(model); 
     return this; 
    }, 
    handleClick: function (e) { 
     e.preventDefault(); 
     postRouter.navigate($(e.currentTarget).attr("href"), 
      {trigger: true}); 
     return false; 
    } 
}); 

var PostFormView = Backbone.View.extend({ 
    tagName: 'form', 
    template: _.template($("#postFormView").html()), 
    initialize: function (options) { 
     this.posts = options.posts; 
    }, 
    events: { 
     'click #submitPost': 'createPost', 
     'click .back' : 'backButton' 
    }, 
    render: function() { 
     this.el.innerHTML = this.template(); 
     return this; 
    }, 
    backButton: function (e) { 
     e.preventDefault(); 
     postRouter.navigate($(e.currentTarget).attr("href"), 
      {trigger: true}); 
     return false; 
    }, 
    createPost: function (e) { 
     e.preventDefault(); 
     var postAttrs = { 
      content: $("#postText").val(), 
      title: $("#postTitle").val(), 
      pubDate: new Date(), 
     }; 
     this.posts.create(postAttrs); 
     postRouter.navigate("/", { trigger: true }); 
     return false; 
    } 
}); 

var PostRouter = Backbone.Router.extend({ 
    initialize: function (options) { 
     this.posts = options.posts; 
     this.main = options.main; 
    }, 
    routes: { 
     '': 'index', 
     'posts/:id': 'singlePost', 
     'post/new': 'newPost' 
    }, 
    index: function() { 
     var pv = new PostsListView({ collection: this.posts }); 
     this.main.html(pv.render().el); 
    }, 
    singlePost: function (id) { 
     var post = this.posts.get(id); 
     var pv = new PostView({ model: post }); 
     this.main.html(pv.render().el); 
    }, 
    newPost: function() { 
     var pfv = new PostFormView({ posts: this.posts }); 
     this.main.html(pfv.render().el); 
    } 
}); 

我也有一些視圖模板在我的索引文件:

<!DOCTYPE html> 
<html> 
<head> 
    <title> Simple Blog </title> 
</head> 
<body> 
<div id="main"></div> 
<script src="/jquery.js"></script> 
<script src="/underscore.js"></script> 
<script src="/backbone.js"></script> 
<script type="text/template" id="postFormView"> 
    <a href="/" class="back">All Posts</a><br /> 
    <input type="text" id="postTitle" placeholder="post title" /> 
    <br /> 
    <textarea id="postText"></textarea> 
    <br /> 
    <button id="submitPost"> Post </button> 
</script> 
<script type="text/template" id="postView"> 
    <a href='/'>All Posts</a> 
    <h1>{{title}}</h1> 
    <p>{{pubDate}}</p> 
    {{content}} 
</script> 
<script src="/app.js"></script> 
<script> 
    var postRouter = new PostRouter({ 
     posts: new Posts(<%- posts %>), 
     main: $("#main") 
    }); 
    Backbone.history.start({pushState: true}); 
</script> 
</body> 
</html> 

查看帖子和主頁工作正常,但當我嘗試創建一個新的帖子時,我從開發工具控制檯得到這個錯誤:

Uncaught ReferenceError: id is not defined 
    at child.eval (eval at _.template (http://localhost:3000/underscore.js:1:1), <anonymous>:6:8) 
    at child.template (http://localhost:3000/underscore.js:1214:21) 
    at child.render (http://localhost:3000/app.js:27:34) 
    at http://localhost:3000/app.js:48:16 
    at Array.forEach (native) 
    at Function._.each._.forEach (http://localhost:3000/underscore.js:79:11) 
    at child.Collection.(anonymous function) [as forEach] (http://localhost:3000/backbone.js:956:24) 
    at child.render (http://localhost:3000/app.js:45:25) 
    at child.index (http://localhost:3000/app.js:118:27) 
    at Object.callback (http://localhost:3000/backbone.js:1242:30) 

服務器是一個簡單的服務器的NodeJS和輸出創建後是這樣的:

{"result":{"ok":1,"n":1},"ops":[{"content":"kljhlkjh","title":"jkhjklh","pubDate":"2016-10-29T10:21:47.793Z","id":12,"_id":"5814783b732bbe153461eca4"}],"insertedCount":1,"insertedId 
s":["5814783b732bbe153461eca4"]} 
+0

[Similar answer](http://stackoverflow.com/a/40308655/1218980)它可以幫助。 –

回答

3

哪裏錯誤?

首先,您需要找出造成錯誤的原因,以及它來自哪裏。

誤差來源於PostListViewrender函數內以下行:

this.el.innerHTML = this.template(this.model.toJSON()); 

而且錯誤是由下劃線的模板渲染拋出。歸結爲:

template: _.template("<a href='/posts/{{id}}'>{{title}}</a>"), 

查看{{id}}?這是發生錯誤時沒有定義的那個。

什麼{{id}}未定義」是指?

您正在通過this.model.toJSON()作爲模板的數據。所以,這意味着this.modelid屬性沒有被定義爲而是

爲什麼我的模型id尚未定義?

這是因爲通過collection's create function創建新模型的步驟是異步

this.posts.create(postAttrs); 
// the model hasn't received an id from the server yet. 
postRouter.navigate("/", { trigger: true }); 

如何等待集合的create調用後?

主幹提供successerror大部分(如果不是全部)其異步函數的回調。

選項散列接受successerror回調將兩者 通過(collection, response, options)作爲參數。

因此,您可以將createPost函數更改爲以下內容,並添加onPostCreated回調函數。

createPost: function(e) { 
    e.preventDefault(); 
    var postAttrs = { 
     content: $("#postText").val(), 
     title: $("#postTitle").val(), 
     pubDate: new Date(), 
    }; 
    this.posts.create(postAttrs, { 
     context: this, 
     success: this.onPostCreated 
    }); 
    return false; 
}, 
onPostCreated: function() { 
    // you don't need to use the router, so your views are self-contained 
    Backbone.history.navigate("/", { trigger: true }); 
},