我使用Backbone.js和Ruby on Rails来渲染帖子集合,但屏幕上没有任何内容呈现。
应用文件
#= require_self
#= require_tree ./templates
#= require_tree ./models
#= require_tree ./views
#= require_tree ./routers
window.IntroProject =
Models: {}
Collections: {}
Routers: {}
Views: {}
init: ->
window.router = new IntroProject.Routers.HomepageRouter({})
Backbone.history.start()
$ ->
IntroProject.init()
模型和集合
class IntroProject.Models.Post extends Backbone.Model
paramRoot: 'post'
class IntroProject.Collections.PostsCollection extends Backbone.Collection
model: IntroProject.Models.Post
url: '/'
路由器
class IntroProject.Routers.HomepageRouter extends Backbone.Router
initialize: (options) ->
@posts = new IntroProject.Collections.PostsCollection()
@posts.fetch()
routes:
'':'index'
index: ->
@view ||= new IntroProject.Views.Posts.IndexView(collection: @posts)
@view.render()
查看
IntroProject.Views.Posts ||= {}
class IntroProject.Views.Posts.IndexView extends Backbone.View
el: '#posts'
template: _.template( $('#home-post-template').html() ) if $("#home-post-template").length
render: ->
@$el.append( @template() )
@
# _.each(@collection, (post) =>
# postHtml = $(@template(post))
# @$el.append( postHtml )
# )
# @
模板
<script type="text/template" id="home-post-template">
<div class="row">
<div class="small-12 columns">
<h2 class="blog-post-title"><%= post.title %></h2>
<small>
<p class="blog-post-meta">Published on <%= post.created_at.strftime('%B %d, %Y') %>
<% if (post.user.email) %>
by <strong><%= post.user.email %></strong>
<% end %>
</p>
</small>
<hr>
<div class="blog-post-body">
<p><%= post.body.html_safe %></p>
</div>
</div>
</div>
</script>
我可以在加载页面时调用render()
因为我执行了console.log('hello')
。我甚至做过console.log(@collection)
。输出:
PostsCollection {models: Array[0], length: 0, _byId: Object, constructor: function, model: function…}
_byId: Object
_idAttr: "id"
length: 2
models: Array[2]
__proto__: ctor
所以他们的帖子都在收藏中。
当我@$el.append( @template() )
时,它post
未定义,所以我@$el.append( @template(post: @collection.models)
。但该帖子未定义。
总的来说,我了解发生了什么,但它不起作用。我错过了一些重要的东西。这是my github repo
更新
答案中建议的更改
路由器
class IntroProject.Routers.HomepageRouter extends Backbone.Router
initialize: (options) ->
@posts = new IntroProject.Collections.PostsCollection()
@posts.fetch({ reset : true })
routes:
'':'index'
index: ->
@view ||= new IntroProject.Views.Posts.IndexView(collection: @posts)
查看
IntroProject.Views.Posts ||= {}
class IntroProject.Views.Posts.IndexView extends Backbone.View
el: '#posts'
template: _.template( $('#home-post-template').html() ) if $("#home-post-template").length
initialize: ->
@listenTo(@collection, 'reset', @render)
render: ->
_.each(@collection, (post) ->
postHtml = @template( post )
@$el.append( postHtml )
, @)
模板,我从post
post.title
现在我通过控制台获得Uncaught ReferenceError: title is not defined
。
答案 0 :(得分:0)
您的集合是异步获取的,这意味着当您在视图上调用render时,数据尚未存在。您可以在console.log(@collection)
中看到它:length
为0。
您的视图需要侦听其集合并在(从)更改/从服务器返回时重新呈现。您可以将此函数添加到您的视图类(不熟悉CoffeeScript,因此编写JS):
initialize : function(){
this.listenTo(this.collection, 'reset', this.render);
}
但是,当fetch call返回时未显式触发重置事件,请将其更改为此(在路由器的设置中):
@posts.fetch({ reset : true });
此外,您观看的render
功能看起来不对我,我写这个
render : function(){
_.each(this.collection, function(model){
var html = this.template( model.toJSON() );
this.$el.append( html );
}, this);
}
这也意味着您需要在模板中替换post
的引用:
<%= title %>
答案 1 :(得分:0)
我能够在一些帮助下找到答案。这是固定代码的样子。如果没有进行任何更改,则省略
路由器
class IntroProject.Routers.HomepageRouter extends Backbone.Router
initialize: (options) ->
@posts ||= new IntroProject.Collections.PostsCollection()
routes:
'':'index'
index: ->
@view ||= new IntroProject.Views.Posts.IndexView(collection: @posts)
@posts.fetch()
查看
IntroProject.Views.Posts ||= {}
class IntroProject.Views.Posts.IndexView extends Backbone.View
el: 'body'
template: _.template( $('#home-post-template').html() ) if $('#home-post-template').length
initialize: ->
@collection.bind "reset", ->
@render()
, @
render: ->
@collection.each (post) =>
$('#posts').append( @template(post.attributes) )
@
模板
<script type="text/template" id="home-post-template">
<div class="row">
<div class="small-12 columns">
<h2 class="blog-post-title"><%= post.title %></h2>
<small>
<p class="blog-post-meta">Published on <%= post.created_at %>
<% if (post.user.email) %>
by <strong><%= post.user.email %></strong>
<% end %>
</p>
</small>
<hr>
<div class="blog-post-body">
<p><%= post.body %></p>
</div>
</div>
</div>
</script>
问题出在fetch和render调用上。当路由器初始化时,我正在获取集合。该集合不会持久存在于视图中。当我在视图上调用render时,没有任何东西可以渲染。
在解决方案中,我现在在初始化视图后拥有fetch()
。初始化视图后,一旦fetch()
成功离开reset
事件,视图就会呈现。我选择将el
设为body
,因为我的活动需要el
为body
。事件在el
内查看何时触发。