2014-01-07 149 views
0

我正在做一个Todo应用程序在主干中。该示例是在下划线模板,但我正在尝试使用hogan模板的骨干。编译好,但渲染不起作用。它抛出错误.. 遗漏的类型错误:物件的“模板”的翻译:不是一个函数未捕获的类型错误:对象[对象对象]的属性'模板'不是函数

这是我的js文件:

var app = app || {}; 

(function ($) { 
    'use strict'; 

    // Todo Item View 
    // -------------- 
    _.templateSettings = { 
       evaluate : /\{\[([\s\S]+?)\]\}/g, 
       interpolate : /\{\{([\s\S]+?)\}\}/g 
      }; 
    app.TodoView = Backbone.View.extend({ 
     //... is a list tag. 
     tagName: 'li', 

     template: Hogan.compile($('#item-template').html()), 

     // The DOM events specific to an item. 
     events: { 
      'click .toggle': 'toggleCompleted', 
      'dblclick label': 'edit', 
      'click .destroy': 'clear', 
      'keypress .edit': 'updateOnEnter', 
      'keydown .edit': 'revertOnEscape', 
      'blur .edit': 'close' 
     }, 

     initialize: function() { 
      this.listenTo(this.model, 'change', this.render); 
      this.listenTo(this.model, 'destroy', this.remove); 
      this.listenTo(this.model, 'visible', this.toggleVisible); 
     }, 

     render: function() { 
      if (this.model.changed.id !== undefined) { 
       return; 
      } 
      //_.each(myAlbum,function(album) { 
      // this.el.append(template.render(album.toJSON())); 
      //}); 
      console.log(Hogan.compile($('#item-template').html())); 

        this.$el.html(this.template(this.model.toJSON())); 
        // Error in the above line 

      this.$el.toggleClass('completed', this.model.get('completed')); 
      this.toggleVisible(); 
      this.$input = this.$('.edit'); 
      return this; 
     }, 

     toggleVisible: function() { 
      this.$el.toggleClass('hidden', this.isHidden()); 
     }, 

     isHidden: function() { 
      var isCompleted = this.model.get('completed'); 
      return (// hidden cases only 
       (!isCompleted && app.TodoFilter === 'completed') || 
       (isCompleted && app.TodoFilter === 'active') 
      ); 
     }, 

     toggleCompleted: function() { 
      this.model.toggle(); 
     }, 

     edit: function() { 
      this.$el.addClass('editing'); 
      this.$input.focus(); 
     }, 

     close: function() { 
      var value = this.$input.val(); 
      var trimmedValue = value.trim(); 

      if (!this.$el.hasClass('editing')) { 
       return; 
      } 

      if (trimmedValue) { 
       this.model.save({ title: trimmedValue }); 

       if (value !== trimmedValue) { 
        this.model.trigger('change'); 
       } 
      } else { 
       this.clear(); 
      } 

      this.$el.removeClass('editing'); 
     }, 

     updateOnEnter: function (e) { 
      if (e.which === ENTER_KEY) { 
       this.close(); 
      } 
     }, 

     revertOnEscape: function (e) { 
      if (e.which === ESC_KEY) { 
       this.$el.removeClass('editing'); 
      } 
     }, 

     clear: function() { 
      this.model.destroy(); 
     } 
    }); 
})(jQuery); 

这是我的HTML

<!doctype html> 
<html lang="en"> 
<head> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 
    <title>Backbone.js • TodoMVC</title> 
<link rel="stylesheet" href="js/assets/base.css"> 
</head> 
<body> 
    <section id="todoapp"> 
    <header id="header"> 
     <h1>todos</h1> 
     <input id="new-todo" placeholder="What needs to be done?" autofocus> 
    </header> 
    <section id="main"> 
     <input id="toggle-all" type="checkbox"> 
     <label for="toggle-all">Mark all as complete</label> 
     <ul id="todo-list"></ul> 
    </section> 
    <footer id="footer"></footer> 
    </section> 
    <div id="form-horizontal"> 
    <p>Double-click to edit a todo</p> 
    <p>Written by <a href="https://github.com/addyosmani">Addy Osmani</a></p> 
    <p>Part of <a href="http://todomvc.com">TodoMVC</a></p> 
    </div> 

    <script type="text/template" id="item-template"> 
    <div class="view"> 
     <input class="toggle" type="checkbox" {{ completed ? 'checked' : '' }}> 
     <label>{{ title }}</label> 
     <button class="destroy"></button> 
    </div> 
    <input class="edit" value="{{ title }}"> 
    </script> 

    <script type="text/template" id="stats-template"> 
    <span id="todo-count"><strong>{{ remaining }}</strong> {{ remaining === 1 ? 'item' : 'items' }} left</span> 
    <ul id="filters"> 
     <li> 
     <a class="selected" href="#/">All</a> 
     </li> 
     <li> 
     <a href="#/active">Active</a> 
     </li> 
     <li> 
     <a href="#/completed">Completed</a> 
     </li> 
    </ul> 
    {[ if (completed) { ]} 
    <button id="clear-completed">Clear completed ({{ completed }})</button> 
    {[ } ]} 
    </script> 

    <script src="js/lib/base.js"></script> 
    <script src="js/lib/hogan-2.0.0.js"></script> 
    <script src="js/lib/jquery.js"></script> 
    <script src="js/lib/underscore.js"></script> 
    <script src="js/lib/backbone.js"></script> 
    <script src="js/lib/backbone.localStorage.js"></script> 
    <script src="js/models/todo.js"></script> 
    <script src="js/collections/todos.js"></script> 
    <script src="js/views/todos.js"></script> 
    <script src="js/views/app.js"></script> 
    <script src="js/routers/router.js"></script> 
    <script src="js/app.js"></script> 
</body> 
</html> 

这真棒..你做得很好。 但我有另一个js文件来添加新的待办事项。这也给错误。 Uncaught TypeError:无法调用未定义的方法'toJSON'。我很新,请帮助我。 我的另一个js文件:

var app = app || {}; 

(function ($) { 
    'use strict'; 



    _.templateSettings = { 
       evaluate : /\{\[([\s\S]+?)\]\}/g, 
       interpolate : /\{\{([\s\S]+?)\}\}/g 
      }; 
    // The Application 
    // --------------- 

    // Our overall **AppView** is the top-level piece of UI. 
    app.AppView = Backbone.View.extend({ 

     // Instead of generating a new element, bind to the existing skeleton of 
     // the App already present in the HTML. 

     el: '#todoapp', 

     // Our template for the line of statistics at the bottom of the app. 

     //statsTemplate: _.template($('#stats-template').html()), 
     statsTemplate:Hogan.compile($('#stats-template').html()), 

     // Delegated events for creating new items, and clearing completed ones. 
     events: { 
      'keypress #new-todo': 'createOnEnter', 
      'click #clear-completed': 'clearCompleted', 
      'click #toggle-all': 'toggleAllComplete' 
     }, 

     // At initialization we bind to the relevant events on the `Todos` 
     // collection, when items are added or changed. Kick things off by 
     // loading any preexisting todos that might be saved in *localStorage*. 
     initialize: function() { 
      this.allCheckbox = this.$('#toggle-all')[0]; 
      this.$input = this.$('#new-todo'); 
      this.$footer = this.$('#footer'); 
      this.$main = this.$('#main'); 
      this.$list = $('#todo-list'); 

      this.listenTo(app.todos, 'add', this.addOne); 
      this.listenTo(app.todos, 'reset', this.addAll); 
      this.listenTo(app.todos, 'change:completed', this.filterOne); 
      this.listenTo(app.todos, 'filter', this.filterAll); 
      this.listenTo(app.todos, 'all', this.render); 

      // Suppresses 'add' events with {reset: true} and prevents the app view 
      // from being re-rendered for every model. Only renders when the 'reset' 
      // event is triggered at the end of the fetch. 
      app.todos.fetch({reset: true}); 
     }, 

     // Re-rendering the App just means refreshing the statistics -- the rest 
     // of the app doesn't change. 
     render: function() { 
      var completed = app.todos.completed().length; 
      var remaining = app.todos.remaining().length; 

      if (app.todos.length) { 
       this.$main.show(); 
       this.$footer.show(); 

       this.$el.html(this.template.render(this.model.toJSON())); 

       this.$footer.html(this.statsTemplate.render({ 
        completed: completed, 
        remaining: remaining 
       })); 

       this.$('#filters li a') 
        .removeClass('selected') 
        .filter('[href="#/' + (app.TodoFilter || '') + '"]') 
        .addClass('selected'); 
      } else { 
       this.$main.hide(); 
       this.$footer.hide(); 
      } 

      this.allCheckbox.checked = !remaining; 
     }, 

     // Add a single todo item to the list by creating a view for it, and 
     // appending its element to the `<ul>`. 
     addOne: function (todo) { 
      var view = new app.TodoView({ model: todo }); 
      this.$list.append(view.render().el); 
     }, 

     // Add all items in the **Todos** collection at once. 
     addAll: function() { 
      this.$list.html(''); 
      app.todos.each(this.addOne, this); 
     }, 

     filterOne: function (todo) { 
      todo.trigger('visible'); 
     }, 

     filterAll: function() { 
      app.todos.each(this.filterOne, this); 
     }, 

     // Generate the attributes for a new Todo item. 
     newAttributes: function() { 
      return { 
       title: this.$input.val().trim(), 
       order: app.todos.nextOrder(), 
       completed: false 
      }; 
     }, 

     // If you hit return in the main input field, create new **Todo** model, 
     // persisting it to *localStorage*. 
     createOnEnter: function (e) { 
      if (e.which !== ENTER_KEY || !this.$input.val().trim()) { 
       return; 
      } 

      app.todos.create(this.newAttributes()); 
      this.$input.val(''); 
     }, 

     // Clear all completed todo items, destroying their models. 
     clearCompleted: function() { 
      _.invoke(app.todos.completed(), 'destroy'); 
      return false; 
     }, 

     toggleAllComplete: function() { 
      var completed = this.allCheckbox.checked; 

      app.todos.each(function (todo) { 
       todo.save({ 
        'completed': completed 
       }); 
      }); 
     } 
    }); 
})(jQuery); 

回答

1

您正在使用编译的Hogan模板不正确。

Hogan.compile()的结果不是一个函数,而是一个对象。这就是为什么你得到“...模板...不是函数”错误。要渲染编译后的Hogan模板,您需要调用该对象的“渲染”功能。

所以你的情况,你需要使用的

this.template.render(this.model.toJSON()) 

代替

this.template(this.model.toJSON()) 

访问http://twitter.github.io/hogan.js以获取更多信息。

相关问题