Javascript Backbone.js:视图对象为';未定义';

Javascript Backbone.js:视图对象为';未定义';,javascript,backbone.js,underscore.js,Javascript,Backbone.js,Underscore.js,下面是我在backbone.js中的基本Todo应用程序代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>Hello World in Backbone.js</title> <style

下面是我在backbone.js中的基本Todo应用程序代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <title>Hello World in Backbone.js</title>
  <style type='text/css'>
    #todoapp ul {
      list-style-type: none;
    }
    #todo-list input.edit {
      display: none;
    }
    #todo-list .editing label {
      display: none;
    }
    #todo-list .editing input.edit {
      display: inline;
    }
  </style>
</head>
<body>

  <section id='todoapp'>
    <header id='header'>
      <h1>Todos</h1>
      <input id='new-todo' placeholder='What needs to be done?'>
      <div>
        <a href="#/">all</a> |
        <a href="#/pending">pending</a> |
        <a href="#/completed">completed</a>
      </div>
    </header>
    <section id='main'>
      <ul id='todo-list'></ul>
    </section>
  </section>

  <script type='text/x-handlebars-template' id='item-template'>
    <div class='view'>
      <input class='toggle' type='checkbox' {{checked}}>
      <label>{{ title }} </label>
      <input class='edit' value='{{ title }}'>
      <button class='destroy'>remove</button>
    </div>
  </script>

  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.js" type="text/javascript"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js" type="text/javascript"></script>

  <script type="text/javascript">
    'use strict'

    var App = {
      Models: {},
      Collections: {},
      Views: {},
      Router: {}
    }

    App.Models.Todo = Backbone.Model.extend({
      defaults: {
        title: '',
        completed: false,
        checked: ''
      },
      toggle: function(){
        var completed = !this.get('completed')
        this.save({
          completed: completed,
          checked: completed ? 'checked' : ''
        });
      }
    });

    App.Collections.TodoList = Backbone.Collection.extend({
      model: App.Models.Todo,
      localStorage: new Store('backbone-todo'),
      completed: function(){
        return this.filter(function(todo){
          return todo.get('completed');
        });
      },
      remaining: function(){
        return this.without.apply(this, this.completed());
      }
    });

    App.Views.Todo = Backbone.View.extend({
      tagName: 'li',
      template: Handlebars.compile($('#item-template').html()),
      render: function(){
        this.$el.html(this.template(this.model.toJSON()));
        this.input = this.$('.edit');
        return this;
      },
      initialize: function(){
        this.model.on('change', this.render, this);
        this.model.on('destroy', this.remove, this);
      },
      events: {
        'dblclick label': 'edit',
        'keypress .edit': 'updateOnEnter',
        'blur .edit': 'close',
        'click .toggle': 'toggle',
        'click .destroy': 'destroy'
      },
      edit: function(){
        this.$el.addClass('editing');
        this.input.focus();
      },
      updateOnEnter: function(e){
        if(e.which == 13){
          this.close();
        }
      },
      close: function(){
        var value = this.input.val().trim();
        if(value){
          this.model.save({title: value});
        }
        this.$el.removeClass('editing');
      },
      toggle: function(){
        this.model.toggle();
      },
      destroy: function(){
        this.model.destroy();
      }
    });

    App.Views.TodoList = Backbone.View.extend({
      el: '#todoapp',
      filter: '',
      initialize: function() {
        this.input = this.$('#new-todo')
        this.collection.on('add', this.addOne, this);
        this.collection.on('reset', this.addAll, this);
        this.collection.fetch();
      },
      events: {
        'keypress #new-todo': 'createTodoOnEnter'
      },
      createTodoOnEnter: function(e) {
        if(e.which !== 13 || !this.input.val().trim()){
          return;
        }
        this.collection.create(this.newAttributes());
        this.input.val('');
      },
      addOne: function(todo){
        if(this.filter === 'completed'){
          return;
        }
        var view = new App.Views.Todo({model: todo});
        $('#todo-list').append(view.render().el);
      },
      addAll: function(){
        this.$('#todo-list').html('');
        switch(this.filter){
          case 'pending':
            _.each(this.collection.remaining(), this.addOne);
            break;
          case 'completed':
            _.each(this.collection.completed(), this.addOne);
            break;
          default:
            this.collection.each(this.addOne, this);
            break;
        }
      },
      newAttributes: function(){
        return {
          title: this.input.val().trim(),
          completed: false
        }
      }
    });

    var todoList = new App.Collections.TodoList;
    var todoListView = new App.Views.TodoList({collection: todoList});

    App.Router = Backbone.Router.extend({
      routes: {
        '*filter': 'setFilter'
      },
      setFilter: function(params){
        todoListView.filter = params.trim() || '';
        todoListView.addAll();
      }
    });


    var router = new App.Router;
    Backbone.history.start();

  </script>

</body>
</html>

Hello World in Backbone.js
#托多普大学{
列表样式类型:无;
}
#todo list input.edit{
显示:无;
}
#待办事项列表。编辑标签{
显示:无;
}
#待办事项列表。编辑输入。编辑{
显示:内联;
}
待办事项
|
|
    {{title}} 去除 “严格使用” 变量应用={ 型号:{}, 集合:{}, 视图:{}, 路由器:{} } App.Models.Todo=Backbone.Model.extend({ 默认值:{ 标题:“”, 已完成:错误, 选中:“” }, 切换:函数(){ var completed=!this.get('completed')) 这个,救命({ 已完成:已完成, 选中:已完成?“选中”:” }); } }); App.Collections.TodoList=Backbone.Collection.extend({ 型号:App.Models.Todo, localStorage:新存储区('backbone-todo'), 已完成:函数(){ 返回此.filter(函数(todo){ 返回todo.get('completed'); }); }, 剩余:函数(){ 返回this.without.apply(this,this.completed()); } }); App.Views.Todo=Backbone.View.extend({ 标记名:“li”, 模板:handlebar.compile($('#项模板').html()), render:function(){ this.el.html(this.template(this.model.toJSON()); this.input=this.$('.edit'); 归还这个; }, 初始化:函数(){ this.model.on('change',this.render,this); this.model.on('destroy',this.remove,this); }, 活动:{ “dblclick标签”:“编辑”, 'keypress.edit':'updateOnEnter', 'blur.edit':'close', '点击.切换':'切换', “单击。销毁”:“销毁” }, 编辑:函数(){ 此.$el.addClass(“编辑”); this.input.focus(); }, 更新输入:函数(e){ 如果(e.which==13){ 这个。关闭(); } }, 关闭:函数(){ var value=this.input.val().trim(); 如果(值){ this.model.save({title:value}); } 这个.el.removeClass('editing'); }, 切换:函数(){ this.model.toggle(); }, 销毁:函数(){ this.model.destroy(); } }); App.Views.TodoList=Backbone.View.extend({ el:'托多普', 筛选器:“”, 初始化:函数(){ this.input=this.$(“#新任务”) this.collection.on('add',this.addOne,this); this.collection.on('reset',this.addAll,this)); this.collection.fetch(); }, 活动:{ “按键#新待办事项”:“createTodoOnEnter” }, createTodoOnEnter:函数(e){ 如果(e.which!==13 | |!this.input.val().trim()){ 返回; } this.collection.create(this.newAttributes()); 这个.input.val(“”); }, addOne:函数(todo){ 如果(this.filter===“已完成”){ 返回; } var view=newapp.Views.Todo({model:Todo}); $(“#待办事项列表”).append(view.render().el); }, addAll:function(){ 这个.$('#待办事项列表').html(''; 开关(此.过滤器){ “未决”案件: _.each(this.collection.remaining(),this.addOne); 打破 案件‘已完成’: _.each(this.collection.completed(),this.addOne); 打破 违约: this.collection.each(this.addOne,this); 打破 } }, newAttributes:function(){ 返回{ 标题:this.input.val().trim(), 已完成:false } } }); var todoList=new App.Collections.todoList; var todoListView=newapp.Views.TodoList({collection:TodoList}); App.Router=Backbone.Router.extend({ 路线:{ “*过滤器”:“设置过滤器” }, setFilter:函数(参数){ todoListView.filter=params.trim(); todoListView.addAll(); } }); var路由器=新的应用程序路由器; Backbone.history.start();
    App.Views.TodoList
    addOne
    方法中,条件
    if(this.filter=='completed')
    导致错误
    未捕获类型错误:无法读取未定义的属性'filter'。为什么
    这个
    (todoListView对象)没有定义?

    \uu0。每个()
    都可以接受一个可选的上下文。试试这个:

     case 'pending':
        _.each(this.collection.remaining(), this.addOne, this);
        break;
      case 'completed':
        _.each(this.collection.completed(), this.addOne, this);
        break;
    

    你需要找出addOne的来电者

    似乎有4种用法

    this.collection.on('add', this.addOne, this);
    this.collection.each(this.addOne, this);
    
    您将此作为上下文传递。这应该没问题

    您询问的错误应该是以下用法之一。 如果要将其用作函数中的视图对象,请将其分别传入

    _.each(this.collection.remaining(), this.addOne);
    _.each(this.collection.completed(), this.addOne);
    

    _.each(this.collection.remaining(), this.addOne, this);
    _.each(this.collection.completed(), this.addOne, this);