【问题标题】:Backbone js - Uncaught type error: Cannot read property 'on' of undefinedBackbone js - 未捕获的类型错误:无法读取未定义的属性“on”
【发布时间】:2014-07-12 11:37:13
【问题描述】:

我有一个使用 Backbone 框架的非常简单的 ToDo List 应用程序。

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>To do List</title>
    <style>
        .completed{
            text-decoration: line-through;
            color: #666;
        }
    </style>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.js"></script>
    <script type="text/javascript" src="js/underscore.js"></script>
    <script type="text/javascript" src="js/backbone.js"></script>
</head>
<body>

    <h1>My Todos</h1>
    <div id="tasks">

        <button class="add">Add Task</button>
        <button class="clear hide">Clear All</button>
        <ul></ul>           

    </div>

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


    <script type="text/javascript">

        var Task = Backbone.Model.extend({
            defaults: {text: 'New task', completed: false}

        });

        var Tasks = Backbone.Collection.extend({
            model: Task,
            el: '#tasks',
            initialize: function(){
                this.collection = new Tasks;
                this.collection.on('add', this.appendNewTask, 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);
            },

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

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

        var TasksView = Backbone.View.extend({
            tagName: 'li',
            el: '#tasks',
            template: _.template($('#taskTemplate').html()),

            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);
            },

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

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

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

            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);
            },

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

        });     

        new TasksView;

    </script>


    <!-- Template JS -->


</body>
</html>

当我访问并加载页面时,我可以在控制台日志中看到一个未捕获的 javascript 错误。

Uncaught TypeError: Cannot read property 'on' of undefined 在第 78 行。

在指示的行号处查看代码,它指向了这个

var TasksView = Backbone.View.extend({
    //.....
    initialize: function(){

        this.model.on('change', this.render, this); // this is the line the console is complaining
        this.model.on('remove', this.unrender, this);
        this.render();
    },
    //.....
});

在接下来的几个小时盯着这个并分析了代码之后,我无法弄清楚为什么在没有任务添加到 TaskView 对象的情况下需要实例化这个模型。当我在模型中添加或删除一个新的任务项时,它应该被初始化。我不太明白这会如何引发异常。

顺便说一句,我是 Backbone.js 和 Underscore.js 的新手。我只是按照在线教程来了解这些框架是如何工作的......

谢谢。

【问题讨论】:

    标签: javascript backbone.js underscore.js


    【解决方案1】:

    您没有将任何模型绑定到您的视图。您可以在实例化新视图时传递模型和/或集合。这些属性将自动绑定到您的视图的this.model / this.collection

    您没有传递模型,因此 this.model 在您的视图中未定义。您应该传递空的任务列表,以便稍后填充它时,onchange 将被触发并且您的视图将重新呈现。

    new TasksView({model: new Tasks()});
    

    【讨论】:

    • 谢谢@Hazaart。这应该够了吧!。但是,在应用此功能时,请刷新页面。我得到一个不同的控制台日志错误。它说 Uncaught RangeError: Maximum call stack size exceeded。这发生在他的行中。 this.collection = 新任务;似乎它在这个集合中进行了大量递归调用,以永久状态扩展函数......这意味着本教程代码中的某个地方没有正确设置......
    • @awongCM 每次初始化您的收藏时,您确实在创建一个新的收藏。您需要删除此行。您应该将您的任务集合中对this.collection 的所有引用替换为this。因为它已经在这个上下文中保存了集合。
    • 谢谢把那个修好了。看起来我在本教程代码中遇到了更多错误,因为我一个接一个地修复了一个小错误。我发现本教程的错误中有很多不好的代码气味......
    • 我遇到了类似的问题......但我只会提出一个问题(我将为我的问题创建一个单独的主题)。我们是否必须将模型绑定到骨干 0.5 中的视图。 1 也是?因为我使用了上述版本并且没有模型/视图绑定的工作
    猜你喜欢
    • 2012-10-05
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 2015-01-06
    • 2017-07-26
    相关资源
    最近更新 更多