我需要更新来自服务器的一些模型数据。 当前,有两个选项:调用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
这样的重置方法?
重置是一个逃生舱口,使您可以在知道自己需要时轻松进行大量的高效渲染。
对于您的情况,只需使用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.
太好了,我明白你的意思。 我可能会选择使用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
事件之外的更改事件( change
和change: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;
};
最有用的评论
@thesmart ,Model#set不会设置缺少的属性,这就是为什么我认为需要Model#reset的原因。
在结案时应该给出理由。 我想知道为什么@ akre54关闭此功能。 骨干模型刻意原始且不受限制,但是缺少Model#reset表示了有关如何使用模型的观点。 从http://backbonejs.org/#Getting -started