【问题标题】:Delay Backbone.sync events延迟 Backbone.sync 事件
【发布时间】:2015-08-20 12:51:02
【问题描述】:

我有一个自定义模型类,其中有一个属性可以告诉我上次获取模型的时间:

var MyModel = Backbone.Model.extend({
    fetched: null,
    fetch: function(options) {
        var self = this;
        return Backbone.Model.prototype.fetch
            .apply(this, arguments)
            .done(function(){
                self.fetched = _.now();
            });
    }
});

然后,我的 View 会监听这个模型的 change 事件并在发生这种情况时呈现自己,根据模型是否已被获取,结果会有所不同:

var MyView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.model, 'change', this.render);
    },
    render: function() {
        if (this.model.fetched == null) {
            // Do something
        }
        else {
            // Do something else
        }
        return this;
    }
});

我的问题是change 事件在Model.fetch 完成后立即触发,甚至在我设置self.fetched = _.now() 之前。 我知道此时我可以手动触发该事件,但这将是多余的,而且我不确定模型在此提取过程中是否实际发生了变化。

有没有办法捕获在调用Backbone.Model.prototype.fetch 期间触发的事件,以便我可以在链接的done 中手动触发它们?

更新:或者,有没有办法让fetch 在触发事件之前成功运行?

【问题讨论】:

  • 这不是它的本意,但覆盖 parse 会让您在将数据应用到模型之前运行代码。
  • @ivarni 是的,从我在源代码中看到的情况来看,这是我在触发 change 事件之前唯一可以 插入 指令的地方(参见第 592 行 @ 987654322@,执行model.set(serverAttrs, options))时触发事件)。但是,此时我会知道数据已经从服务器成功接收到了,但是如果已经成功set到模型就不知道了。我开始认为实现我想要的唯一方法是重写Backbone.Model.fetch

标签: jquery backbone.js jquery-deferred backbone-events


【解决方案1】:

时间已过,因为.done() 处理程序在稍后的事件线程中触发,类似于setTimeout()

有没有办法捕获在调用 Backbone.Model.prototype.fetch 期间触发的事件,以便我可以在我的链式完成中手动触发它们?

不,我希望,没有黑客 Backbone,你真的不想这样做。但是,您可以利用 Backbone 触发和侦听自定义事件的能力。

例如,您可以有一个自定义的fetched 事件,由MyModel.fetch() 中的.done() 回调触发,并在您喜欢的任何地方收听。

MyModel.model.fetched 时间戳的需求将消失,因为与change 不同,自定义事件只会从那个地方触发。

var MyModel = Backbone.Model.extend({
    fetch: function(options) {
        var self = this;
        return Backbone.Model.prototype.fetch
            .apply(this, arguments)
            .done(function() {
                self.trigger('fetched');
            });
    }
});

虽然文档只讨论了与.on() 相关的自定义事件,但它们同样可以通过.listenTo() 来收听。没有什么可以阻止您收听标准的change 以及自定义的fetched 事件。

此策略将允许(例如)您的“做某事”和“做其他事情”在单独的侦听器中执行,而不是作为单个侦听器的分支:

var MyView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.model, 'change', this.render_on_change);
        this.listenTo(this.model, 'fetched', this.render_on_fetch);
    },
    render_on_change: function() {
        /* Do something */
    },
    render_on_fetch: function() {
        /* Do something else */
    }
});

变化无穷无尽。您可能需要使用它,直到您获得适合您的应用程序的确切内容。

为了介绍this.listenTo(this.model, 'fetched', ...);,恐怕你得硬着头皮对每个需要响应该事件的视图进行更改。这是不可避免的。

从积极的方面来说,任何当前拥有this.listenTo(this.model, 'change', ...); 并且不需要收听fetched 的模型都可以保持原样。

【讨论】:

    【解决方案2】:

    您可以为 fetch 函数提供一个成功回调,并且可以摆脱模型中的代码。

    var MyView = Backbone.View.extend({
        initialize: function() {
            var self=this
            this.listenTo(this.model, 'change', this.render);
            this.model.fetch({
                success: function(){
                   self.model.fetched= _.now();
            })
        },
        render: function() {
            if (this.model.fetched == null) {
                // Do something
            }
            else {
                // Do something else
            }
            return this;
        }
    });

    【讨论】:

    • 我发现此解决方案存在两个问题:我必须在每个侦听我的模型的视图中都这样做,如果在渲染视图后更新模型,它将无法工作。跨度>
    猜你喜欢
    • 2012-07-23
    • 2015-11-21
    • 2011-01-17
    • 2016-08-01
    • 1970-01-01
    • 2016-03-22
    • 2015-01-17
    • 2012-07-11
    • 2010-09-30
    相关资源
    最近更新 更多