Backbone listenTo不会因为财产变化而开火

时间:2015-07-18 17:17:28

标签: javascript backbone.js

我是Backbone的新手,我有一些应该监听属性更改并触发函数的代码。我在网上看到的关于如何使用listenTo的所有东西似乎都涵盖了这种情况,所以我不知道我在忽视什么。

为了更好地理解我做了一个不那么复杂的示例,它只包含一个模型,一个视图并设置了listenTo。问题仍然存在于较小的样本中。

我已经编写了一些代码来记录哪些函数被触发以及按什么顺序触发。当我看到运行此代码的时候几乎是我期望的顺序,除了从不调用onSomethingChanged。

var AppView = Backbone.View.extend({
    initialize: function(){
        this.listenTo(this.model, 'change:hasName', this.onSomethingChanged);

        $('#steps').append('<li>AppView initialize</li>');
        this.model.setName('Test Name');
    },
    onSomethingChanged: function(){
        $('#steps').append('<li>AppView onSomethingChanged</li>');
    }
});

var SomeModel = Backbone.Model.extend({
    initialize: function(){
        this.bind('change:name', this.onNameChanged, this);
        this.set({'name': 'Nothing'});

        $('#steps').append('<li>SomeModel initialize</li>');
    },
    onNameChanged: function(status, name){
        this.set({'hasName': name != null});

        $('#steps').append('<li>SomeModel onNameChanged</li>');
    },
    setName: function(name){
        this.set({'name': name});

        $('#steps').append('<li>SomeModel setName</li>');
    }
});

$(function(){
    window.app = new AppView({model: new SomeModel()});
});

我在这里设置了一个小提琴:https://jsfiddle.net/hamveefz并显示顺序如下:

  1. SomeModel onNameChanged
  2. SomeModel初始化
  3. AppView初始化
  4. SomeModel onNameChanged
  5. SomeModel setName
  6. 我假设在SomeModel的onNameChanged函数中,然后使用hasName属性执行'this.set'会自动导致侦听器调用hasName的更改。

    有人可以向我解释我在哪里出错吗?

1 个答案:

答案 0 :(得分:3)

调用set并不一定会改变任何内容。例如,这个:

model.set('property', model.get('property'));

不会触发'change'事件,因为它实际上没有做任何事情。

您的模型initialize设置名称:

this.set({'name': 'Nothing'});

'change:name'处理程序受该点约束,因此onNameChanged将被调用,hasName将设置为true

然后构建视图,其initialize将:

this.listenTo(this.model, 'change:hasName', this.onSomethingChanged);
this.model.setName('Test Name');

您认为setName应该触发'change:hasName'事件,但事实并非如此。此时hasName属性已为true,您将执行set('hasName', true),因此不会更改。

最好将name作为nullundefined离开,直到它实际设置为止。您要从模型的this.set({'name': 'Nothing'});中删除initialize并添加:

defaults: {
    name: null,
    hasName: false
}

然后调整以查看(及其模板)以处理“无名”案例。