CoffeeScript / Backbone / Marionette - 教程示例转换和范围问题

时间:2012-05-09 23:06:34

标签: javascript backbone.js coffeescript marionette

我正在尝试在CoffeeScript中创建此示例的基本版本:http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/。所有依赖项都按照我编写的顺序(在正文中)声明为.coffee文件,并且jQuery + Underscore + Backbone + Marionette在头部。

我有一个模型, thing.coffee

$ ->

  console.log 'load model'

  class Thing extends Backbone.Model

    defaults:
      myValue: null

   initialize: ->
     console.log 'new thing'

  window.Thing = Thing

我的第一个打嗝是确定范围:如果我没有声明window.Thing,则下一个文件(Things的集合)无法找到模型Thing,依此类推我在那里做错了什么?

我有一个集合 things.coffee

$ ->

  console.log 'load collection'

  class Things extends Backbone.Collection

    model: Thing

  window.Things = Things

我有一个木偶视图, thing_view.coffee

$ ->

  console.log 'load composite model view'

  ThingView = Backbone.Marionette.ItemView.extend(
    template: '#template-thing'
    tagName: 'tr'
  )

  window.ThingView = ThingView

我有一个木偶视图, things_view.coffee

$ ->

  console.log 'load composite collection view'

  ThingsView = Backbone.Marionette.CompositeView.extend(
    tagName:  'table'
    id: 'things'
    template: '#template-things'
    itemView: ThingView
    appendHtml: (collectionView, itemView) ->
      collectionView.$('tbody').append itemView.el
  )

  window.ThingsView = ThingsView

我有一个应用程序 myapp.coffee

$ ->

  console.log 'load app'

  # Load default data
  thingsCollection = new Things([ 
    new Thing(myValue: 'uno'), 
    new Thing(myValue: 'dos')
  ])

  data:
    thingsCollection: thingsCollection

  # Create application, specify default layouts
  MyApp = new Backbone.Marionette.Application()
  MyApp.addRegions singleRegion: '#content'

  # On application init...
  MyApp.addInitializer (data) ->
    console.log 'Init application...'
    thingsView = new ThingsView(collection: data.thingsCollection)
    MyApp.singleRegion.show data.thingsView

  # Start application
  MyApp.start data

我的html文件如下:

<div id="content">
    <script type="text/template" id="template-things">
       <thead>
          <tr class='header'>
             <th>myValue</th>
          </tr>
      </thead>
      <tbody>
      </tbody>
    </script>
    <script type="text/template" id="template-thing">
       <td><%= myValue %></td>
    </script>
</div>

关注console.log

load model
load collection
load composite model view
composite collection view
load app
Init application...
Uncaught TypeError: Cannot call method 'render' of undefined

所以,不用说我对发生了什么感到困惑 - 我确信这里有很多错误,所以请帮忙!

2 个答案:

答案 0 :(得分:4)

window.Thing事件是Coffeescript全局命名空间污染避免的副产品。解决问题的惯用方法是use an App namespace

仅在DOM加载时初始化类是Backbone anti-pattern。如果您对类进​​行命名空间,那么您只需确保以正确的顺序加载它们(在集合视图之前的项目视图),并且可以立即创建它们而不是在页面加载之后。

您能告诉我们Uncaught TypeError发生在哪里吗?

答案 1 :(得分:1)

  

如果我没有声明window.Thing,则下一个文件(Things的集合)无法找到模型Thing,依此类推。我在那里做错了什么?

CoffeeScript编译器将每个文件包装在一个自执行函数中,因此Thing是包装器的本地文件,除非您通过将其放入window强制全局化。

我认为你真正的问题就在这里:

MyApp.addInitializer (data) ->
  console.log 'Init application...'
  thingsView = new ThingsView(collection: data.thingsCollection)
  MyApp.singleRegion.show data.thingsView

您创建ThingsView并将其存储在thingsView中。但是,您尝试将data.thingsView传递给MyApp.singleRegion.showdata.thingsView中没有任何内容,因此当Marionette内部的某些内容尝试view.render()时,您会收到投诉。我想你想要这个:

  thingsView = new ThingsView(collection: data.thingsCollection)
  MyApp.singleRegion.show thingsView

或者这个:

  data.thingsView = new ThingsView(collection: data.thingsCollection)
  MyApp.singleRegion.show data.thingsView

取决于此data对象的全部内容。