骨干模型虚拟属性?

时间:2014-05-11 19:59:21

标签: javascript backbone.js

我在骨干模型中需要虚拟属性,但骨干似乎不支持这一点,我将如何自己实现这一点。

虚拟属性是指仅在客户端维护的属性,不保存/同步到服务器。我想使用它们来存储仅与客户端视图呈现相关的状态信息,例如是否选择/检查模型。我将在视图的模板渲染中使用模型属性,但我不希望这些值发送到服务器或保存在数据库中。

2 个答案:

答案 0 :(得分:2)

如果您想在客户端仅在模型上存储属性,为什么不使用:     model.set({attribute: "client-side only"}) 代替:     model.fetch()

为避免触发更改事件,您可以传入:     model.set({silent:true}) 虽然文档不推荐这个。如果您感觉更冒险,您还可以覆盖set方法,使其真正沉默,如本答案所述:

Truly change a model attribute silently in Backbone.js?

更新:

环顾四周: Backbone.js partial model updateExclude model properties when syncing (Backbone.js)

看起来你最简单的选择是: model.save(model.changedAttributes(), {patch: true});

或者如果您需要以良好的方式创建/更新这些对象,您可以覆盖主干sync,如下所示:

 Backbone.Model.extend({

  // Overwrite save function
  save: function(attrs, options) {
   options || (options = {});

    // Filter the data to send to the server
    delete attrs.selected;
    delete attrs.dontSync;

    options.data = JSON.stringify(attrs);

    // Proxy the call to the original save function
    Backbone.Model.prototype.save.call(this, attrs, options);
  }
});

信用:Simon Boudrias

答案 1 :(得分:1)

一些选择:

您可以创建一个通用主干模型并使用它来存储&听取视图状态的属性。

StatefulView = Backbone.View.extend({
    initialize: function(options) {
        this.state = new Backbone.Model({
            selected: !!options.selected
        });
        this.listenTo(this.state, 'change:selected', this.renderSelectedState);
    },

    // ...
});

我建议不要在模型中存储任何类型的与视图相关的属性,因为当您的应用程序增长时,如果您在多个可选列表中显示相同的模型,则它不是可伸缩的解决方案。但是......您可以覆盖模型的toJSON函数以删除您不想保留的属性:

ModelWithClientAttributes = Backbone.Model.extend({
    toJSON: function(withClientAttrs) {
        var json = Backbone.Model.prototype.toJSON.call(this);
        if (withClientAttrs) return json;
        return _(json).omit(this.clientAttrs);
    },

    // ...
});

// Extend from that base class when defining your model, and define the 'clientAttrs' property
Post = ModelWithClientAttributes.extend({
    clientAttrs: ['selected', 'checked'],
    // ...
});

// Then, in your view:
render: function() {
    this.$el.html(
        this.template(
            this.model.toJSON( true )
        )
    );
}

// Backbone.sync will call toJSON without arguments, so they will receive the filtered json representation
var post = new Post({
    selected: true,
    title: 'May Snow Storm',
    body: '...'
});
post.save();
console.log(post.toJSON()); // {"title": "May Snow Storm", "body": "..."}
console.log(post.toJSON(true)); // {"selected": true, "title": "May Snow Storm", "body": "..."}

最安全和最好的解决方案可能就是将您希望在服务器端代码中保留的属性列入白名单。