2014-06-07 57 views
0

不久前,我在Stackoverflow上发布了this问题。基本上,这是我第一次尝试在我自己的项目中尝试使用Backbone.js,之前的发布问题已得到解决。Backbone.js - 未捕获的参考错误

但现在,当加载此页面时,我可以看到在Chrome控制台窗口中显示以下javascript错误。

Uncaught ReferenceError: completed is not defined VM46:6 
(anonymous function) VM46:6 
_.template.template underscore.js:1308 
Backbone.View.extend.render example_addbutton.html:69 
Backbone.View.extend.initialize example_addbutton.html:65 
Backbone.View backbone.js:1031 
child backbone.js:1658 
(anonymous function) 

经过一个小时的故障排除后,我将问题追溯到代码的这一部分。

<script id="taskTemplate" type="text/template"> 
    <span class="<%=completed ? 'completed' : 'incomplete' %>"><%= text %></span> 
    <button class="complete"></button> 
    <button class="delete"></button> 
</script> 

建议Underscore的模板引擎无法理解“已完成”变量。

当我已经在这里申报时,这怎么可能?

var Tasks = Backbone.Collection.extend({ 
      model: Task, 

      completed: function(){ 
       return _.filter(this.models, function(model){ 
        return model.get('completed'); 
       }); 
      }, 
     }); 

我做错了什么?

+1

错误与'template'方法有关,您应该在调用模板函数时传递'completed'属性。您发布的代码与抛出的错误无关。 – undefined

+0

谢谢!在重新读取代码之后,我意识到在将变量传递给模板引擎进行渲染时,我的骨干模型声明和完成的属性出了问题。我目前正在调查。干杯! – awongCM

+0

提示:你可以缩短你的'Tasks'集合:因为所有的Underscore收集方法都可以在Backbone集合中使用,所以你可以将'completed'减少到'return this.filter(...); ';) –

回答

0

终于找到了解决办法。

经过在线挖掘以获得快速解决方案之后,我不得不重构所谓的“教程”代码以使应用程序正常工作。

原来它的Backbone View逻辑写得不好,因为它试图呈现主应用程序屏幕以及在代码的一部分中添加的新项目。所以我不得不把它拿出来放在另一个Backbone View逻辑中,并带有适当的事件监听器。

var TasksView = Backbone.View.extend({ 
    tagName: 'li', 

    template: _.template($('#taskTemplate').html()), 

    events: { 
     'click .delete': 'delete', 
     'click .complete': 'updateStatus', 
     'dblclick span': 'edit' 
    }, 

initialize: function(){ 
      this.model.on('change', this.render, this); 
      this.model.on('remove', this.unrender, this); 
      this.render(); 
    }, 

    render: function(){ 
      var markup = this.template(this.model.toJSON()); 
      this.$el.html(markup); 
      return this; 
    }, 

    unrender: function(){ 
      this.$el.remove(); 
    }, 

    delete: function(){ 
      this.model.destroy(); 
      this.$el.remove(); 
    }, 

    updateStatus: function(){ 
      this.model.set('completed', !this.model.get('completed')); 
    }, 

    edit: function(){ 
      var text = prompt('What should we change your task to?', this.model.get('text')) 
      this.model.set('text',text); 
    }, 

}); 

var AppView = Backbone.View.extend({ 
    el:'#tasks', 

    events: { 
     'click .add': 'add', 
     'click .clear': 'clearCompleted' 
    }, 

    initialize: function(){ 
     this.collection = new Tasks(); 
     this.collection.on('add', this.addOneTask, this); 
     this.items = this.$el.children('ul'); 

    }, 

    add: function(){ 
     var text = prompt('What do you need to do?'); 
     var task = new Task({text: text}); 
     this.collection.add(task); 
    }, 

    render: function(){ 

    }, 

    addOneTask: function(task){ 
     var view = new TasksView({model:task}); 
     this.items.append(view.render().el); 
    }, 

    clearCompleted: function(){ 
     var completedTasks = this.collection.completed(); 
     this.collection.remove(completedTasks); 
    } 

}); 

瞧!有用!

+0

提示:考虑实现一个'TasksView'并在其中封装_list_呈现(侦听集合中的'add'和'remove')。现在叫做'TasksView',绑定到模型,然后渲染一个'Task'(只在模型上侦听“change”)。 –

+0

对不起......我不确定我很追随你。在我按照上面的方法修改之前,它会不会和原来的代码一样?你能否演示如何简单地模拟你的代码? – awongCM

相关问题