Backbone: 向Backbone.Model添加“重置”方法

创建于 2014-07-31  ·  22评论  ·  资料来源: jashkenas/backbone

我需要更新来自服务器的一些模型数据。 当前,有两个选项:调用Model.set ,或直接设置Model.attributes 。 我不想记录更改,但是我也不能使用silent因为我需要更新各自的视图。 所以,我写了一个猴子补丁:

Backbone.Model.prototype.reset = (attributes, options) ->
    attrs = attributes || {};
    if options.parse
      attrs = this.parse(attrs, options) || {}

    @set(attrs, options);
    <strong i="9">@changed</strong> = {};

想知道为什么Backbone.Model没有像Backbone.Collection这样的重置方法?

question

最有用的评论

@thesmart ,Model#set不会设置缺少的属性,这就是为什么我认为需要Model#reset的原因。

在结案时应该给出理由。 我想知道为什么@ akre54关闭此功能。 骨干模型刻意原始且不受限制,但是缺少Model#reset表示了有关如何使用模型的观点。 从http://backbonejs.org/#Getting -started

从哲学上讲,Backbone试图发现最小的数据结构集(模型和集合)和用户界面(视图和URL)原语,这些原语在使用JavaScript构建Web应用程序时通常很有用。

所有22条评论

重置是一个逃生舱口,使您可以在知道自己需要时轻松进行大量的高效渲染。

对于您的情况,只需使用set

您可以在不使属性更改变脏的情况下进行设置吗?

2014年8月1日上午7:28,Jeremy Ashkenas [email protected]写道:

重置是一个逃生舱口,使您可以在知道自己需要时轻松进行大量的高效渲染。

对于您的情况,只需使用set。

-
直接回复此电子邮件或在GitHub上查看。

在您的情况下可以在Model.set({})之前调用Model.clear()吗? 这样,您将不会扩展当前属性,而是将其替换。 如果您不想在模型上触发两个“更改”事件,则Model.clear()还支持静默选项。

我同意这种方法不存在。 我还考虑过结合使用model.clear()model.set() 。 然后我遇到了这个问题,我现在两次触发change事件。
调用model.clear()不能使用silent选项,因为我还想在属性未设置时触发change事件。

model.reset()方法将采用新的属性哈希,并用新属性哈希中不存在的旧属性键的undefined值填充此哈希。

Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        if (key in attrs) continue;
        attrs[key] = void 0;
    }

    return this.set(attrs, options);
};

@lennerd

关于什么:

Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        this.unset(key, {silent:true});
    }
    return this.set(attrs, options);
};

不,这无济于事。 假设您在模型的当前属性哈希中有一个键foo ,但在传递给model.reset()的新attrs哈希中不存在该键。 当我听change:foo事件时,不会用新值undefined触发它,因为我们在静默模式下使用了model.unset()

Backbone.Model.prototype.reset = function(attrs, options) {
    for (var key in this.attributes) {
        this.unset(key, {silent:true});
    }
    return this.set(attrs, options);
};

var bar = new Backbone.Model();

bar.on('change', function(model) {
    console.log('The model bar has been changed.');
});

bar.on('change:foo', function(model, foo) {
    console.log('Foo has been changed to: ' + foo);
});

bar.set(foo, 'test');
// => The model bar has been changed.
// => Foo has been changed to: test

bar.reset({ foo2: 'test2' });
// => The model bar has been changed.
// Foo was resetted but no change event has been triggered.

http://jsfiddle.net/lennerd/3s1Ltwgu/

太好了,我明白你的意思。 我可能会选择使用this.unset(key, options)来覆盖this.attributes,但这只是换掉attrs[key] = void 0; :panda_face:

请原谅我所表现出的任何无知,因为我对ebone.js还是比较陌生,但是正在讨论的行为听起来像Model.fetch描述说:

从服务器重置模型状态

好像change事件仍被触发,但不会使模型“肮脏”。 当您要基于服务器响应重置属性时,是否存在无法采用这种方法的原因? 我可以想象,只有当模型作为另一个操作的副作用而发生变化时,才会发生这种情况,但是通常认为这种副作用是不良的编程,应该尽可能避免。 如果副作用无法避免,那么发送“更新模型XYZ”响应标志而不是新模型属性,并在每次看到这样的响应时触发fetch也许更有意义。

同样,请原谅我在此评论中表现出的任何无知。

@kolorahl

OP想要实现的是清除当前模型属性,并传递一个新的JSON,该JSON成为模型的新属性。 以这种方式,如果已经有了JSON,我们就不想打后端。

我在某种程度上同意@ lupugabriel1的clear + set方法。 但是我认为这是需要考虑的一项功能。 类似于Backbone.Collection#reset

我之所以需要这样做,是因为世界在变化。 Backbone假定Model#fetch()XHR是从服务器加载数据的主要方法,但是我们正在使用websockets做更多的事情。 当数据被推送到客户端时,调用.fetch是多余的,我们需要一种不错的方式来侧加载数据并仍然获得事件钩子来触发。

为什么不使用#set

@jridgewell,因为#set将使属性变脏。 让我们尝试使用set看看会发生什么:

function callback(data_from_server) {
  console.info(data_from_server);
  m = new Backbone.Model(data_from_server);
  m.set('foo', 'what?', {silent: true});
  console.info(m.changedAttributes())
}

实际结果:

{foo: 'bar'}
{foo: "what?"}

期望的结果:

{foo: 'bar'}
false

当状态更改为与服务器不同步时,使用Set即可,但是需要Model#reset,因为无法将状态标记为与服务器同步。

我最终为此功能编写了另一个猴子补丁:

/**
 * Allow for side-loading data from the server, calling the sync event afterwards.
 * <strong i="6">@param</strong> attributes
 * <strong i="7">@param</strong> options
 */
Backbone.Model.prototype.sync_set = function(attributes, options) {
  var attrs = attributes || {};
  if (options.parse) {
    attrs = this.parse(attrs, options) || {}
  }

  this.set(attrs, options);
  this.changed = {};
  this.trigger('sync', this, attributes, options);
  return this;
}
function callback(data_from_server) {
  console.info(data_from_server);
  m = new Backbone.Model(data_from_server);
  m.set('foo', 'what?', {silent: true});
  console.info(m.changedAttributes())
}
{foo: 'bar'}
false

这可能还需要取消设置丢失的项目。 不知道Model#set(attributes)是否这样做。

正如@lennerd所指出的那样,调用clear()后跟set()不是一个好选择,因为它

1)触发两个change事件,
2)如果在clear调用中使用silent:true ,则不会获得未设置属性的更改事件。

collection.reset()非常直观,我认为Model可以真正从等效方法中受益。 我发现自己一直在尝试使用model.reset(attrs) ,当它不存在时总是会感到失望。 :(

我继续并创建了一个小扩展以向Backbone添加一个有效的reset方法。Model: Backbone-Model-Reset

同意-本地使用会很有用。 我只需要重置属性而不要像clear()那样处理'id'属性。 这是要点

@thesmart ,Model#set不会设置缺少的属性,这就是为什么我认为需要Model#reset的原因。

在结案时应该给出理由。 我想知道为什么@ akre54关闭此功能。 骨干模型刻意原始且不受限制,但是缺少Model#reset表示了有关如何使用模型的观点。 从http://backbonejs.org/#Getting -started

从哲学上讲,Backbone试图发现最小的数据结构集(模型和集合)和用户界面(视图和URL)原语,这些原语在使用JavaScript构建Web应用程序时通常很有用。

据我所知,Backbone的数据模型与REST不兼容
因为没有办法在客户端上安全地对服务器状态进行建模
模型已构建。 构造新模型是唯一的方法
没有重置的全新状态。

2016年7月5日星期二,pgifford [email protected]写道:

@thesmart https://github.com/thesmart,Model#set不会丢失
属性,这就是为什么我认为需要Model#reset的原因。

在结案时应该给出理由。 ID
想知道为什么@ akre54 https://github.com/akre54关闭了它。
骨干模型是故意原始的,并且不受质疑。
缺少Model#reset表示有关如何使用模型的意见。 从
http://backbonejs.org/#Getting -started

从哲学上讲,骨干网是试图发现最小的
数据结构(模型和集合)和用户界面(视图和
URL)原语在构建Web应用程序时通常非常有用
使用JavaScript。

-
您收到此邮件是因为有人提到您。
直接回复此电子邮件,在GitHub上查看
https://github.com/jashkenas/backbone/issues/3253#issuecomment -230586424,
或使线程静音
https://github.com/notifications/unsubscribe/AARJLQ8-BGeV0X_owHVpyPQAdeiMweNMks5qSriDgaJpZM4CTBHH

我需要一个模型reset并继续在Backbone的spirit_中制作。 我在Backbone的个人扩展中使用了此功能。

它比简单的.clear后跟.set更好,因为它将默认值合并回模型中,让任何传递的属性像初始化时一样覆盖它们。

/**
 * Clears the model's attributes and sets the default attributes.
 * <strong i="10">@param</strong> {Object} attributes to overwrite defaults
 * <strong i="11">@param</strong> {Object} options  to pass with the "set" call.
 * <strong i="12">@return</strong> {Backbone.Model}  this object, to chain function calls.
 */
reset: function(attributes, options) {
    options = _.extend({ reset: true }, options);

    // ensure default params
    var defaults = _.result(this, 'defaults'),
        attrs = _.defaults(_.extend({}, defaults, attributes || {}), defaults);

    // apply
    this._reset(attrs, options);

    // triggers a custom event, namespaced to model in order
    // to avoid collision with collection's native reset event
    // when listening to a collection.
    if (!options.silent) this.trigger('model:reset', this, options);

    return this;
},

/**
 * Private method to help wrap reset with a custom behavior in child
 * classes.
 * <strong i="13">@param</strong>  {Object} attributes to overwrite defaults
 * <strong i="14">@param</strong>  {Object} options  to pass with the "set" call.
 */
_reset: function(attrs, options) {
    this.clear({ silent: true }).set(attrs, options);
},

如果不是silent: true ,它还会触发自定义model:reset事件之外的更改事件( changechange:attribute )。 可以轻松地对其进行自定义以仅触发model:reset事件,但是我认为在重置模型时,更改事件应始终触发。

我已经调整了lennerd https://github.com/jashkenas/backbone/issues/3253#issuecomment -58789524的解决方案。

Backbone.Model.prototype.reset = function(attrs, options) {
    var missing = {};
    for (var key in this.attributes) {
        if (key in attrs) continue;
        attrs[key] = undefined;
        missing[key] = true;
    }
    // trigger all change events at the same time
    this.set(attrs, options);
    // remove missing attributes completely
    for (var key in missing) {
        // no silent option here in case  attributes changed again meanwhile (edge case)
        this.unset(key)
    }
    return this;
};
此页面是否有帮助?
0 / 5 - 0 等级