ReferenceError:todoItem未定义Backbone + CoffeeScript

时间:2013-02-02 13:25:11

标签: javascript jquery backbone.js coffeescript underscore.js

我正在尝试使用带有coffeescript的骨干而不是javascript:

TodoItem = Backbone.Model.extend(
  toggleStatus: ->
    if @.get 'status' is "incomplete"
      @.set 'status': 'complete' 
    else
      @.set 'status': 'incomplete'
    @.save()  
    )

todoItem = new TodoItem(
  description: 'I play the guitar'
  status: 'incomplete'
  id: 1
)

TodoView = Backbone.View.extend(
  tagName: 'div'
  id: "box"
  className: 'red-box'

  events: 
    "click h3": "alertStatus"
    'change input': 'toggleStatus'

  template: 
    _.template "<h3> <input type=checkbox #{ print "checked" if status is "complete"} /> <%= description %></h3>"

  initialize: ->
    @.model.on 'change', @.render, @
    @.model.on 'destroy', @.remove, @

  toggleStatus: ->
    @.model.toggleStatus()

  alertStatus: ->
    alert('Hey you clicked the h3!')

  remove: ->
    @.$el.remove()

  render: ->
    @.$el.html @.template(@.model.toJSON())
)

todoView = new TodoView({model: todoItem})
todoView.render()
console.log todoView.el

如果我在控制台中尝试:

todoItem.set({description: 'asdfadfasdfa'});

我明白了:

ReferenceError: todoItem is not defined

另外,我无法看到我体内的div:

<div id="box" class="red-box">
  <h3>
  <input type="checkbox" undefined>
  "I play the guitar"
  </h3>
 </div>

但我可以在控制台中看到这个div。

错误在哪里?

谢谢!

1 个答案:

答案 0 :(得分:1)

CoffeeScript的一个好处是,您可以使用@foo代替@.foo。写的少一点,阅读的好一点。


您不必使用Backbone的.extend(),因为CoffeeScript具有以完全兼容的方式工作的类:

class TodoView extends Backbone.View
  tagName: 'div'
  id: 'box' # don't do this if you have more than one TodoView on the page at once
  className: 'red-box'

todoItem未定义,因为CoffeeScript会将所有代码包装在“立即执行的函数表达式”中,从而防止将变量泄漏到全局范围(这是一件好事)。来自文档:

  

虽然为了清楚起见在本文档中进行了限制,但所有CoffeeScript输出都包含在一个匿名函数中:(function(){ ... })();此安全包装器与自动生成var关键字相结合,使得污染非常困难意外的全局命名空间。

如果要检查局部变量,请在Chrome的调试器或Firebug中设置断点。


我担心这段代码:

_.template "... #{ print "checked" if status is "complete"} ..."

什么是print?你在哪里定义的?就此而言,status在哪里?你的意思是@status


最后,您没有看到div的原因是您从未将其添加到DOM中。 .render()呈现元素...但它不会自动将它插入页面。你必须自己做:

todoView.render()
$('body').append(todoView.el) # (or wherever you want it to go)