Javascript 如何在 ember-data 模型中表示数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12168570/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:17:55  来源:igfitidea点击:

How to represent arrays within ember-data models?

javascriptember.jsember-data

提问by dechov

Is it necessary to use DS.hasManypointing to a DS.Modelwhen a model contains an array? Even if the array elements are not really models (no IDs or endpoints of their own)? Is there a better way?

当模型包含数组时是否需要使用DS.hasMany指向 a DS.Model?即使数组元素不是真正的模型(没有自己的 ID 或端点)?有没有更好的办法?

I am using DS.hasMany, but my extended DS.RESTAdapteris throwing me a 404 trying to access the model, even though I'm never calling findon it, and hasManyis called with { embedded: true }. I am seeing this error for the first time (apparently in connection with this model, since it goes away without it):

我正在使用DS.hasMany,但我的扩展DS.RESTAdapter向我抛出 404 试图访问模型,即使我从不调用find它,并且hasMany使用{ embedded: true }. 我第一次看到这个错误(显然与这个模型有关,因为没有它它就会消失):

Uncaught Error: assertion failed: Emptying a view in the inBuffer state is not allowed and should not happen under normal circumstances. Most likely there is a bug in your application. This may be due to excessive property change notifications. ember-latest.js:43

What does this mean and what might be causing it?

这是什么意思,可能是什么原因造成的?

Here's the stack trace:

这是堆栈跟踪:

Ember.assert ember-latest.js:43
Ember.View.states.inBuffer.empty ember-latest.js:13644
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
Ember.CollectionView.Ember.ContainerView.extend.arrayWillChange ember-latest.js:14477
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
Ember.Array.Ember.Mixin.create.arrayContentWillChange ember-latest.js:6963
Ember.ArrayProxy.Ember.Object.extend.arrangedContentArrayWillChange ember-latest.js:9281
Ember.ArrayProxy.Ember.Object.extend._arrangedContentWillChange ember-latest.js:9235
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
notifyObservers ember-latest.js:1872
Ember.notifyBeforeObservers ember-latest.js:2016
propertyWillChange ember-latest.js:2594
iterDeps ember-latest.js:2077
dependentKeysWillChange ember-latest.js:2092
propertyWillChange ember-latest.js:2592
set ember-latest.js:1416
DS.Model.Ember.Object.extend.dataDidChange ember-data-latest.js:3145
Map.forEach ember-latest.js:1273
OrderedSet.forEach ember-latest.js:1145
Map.forEach ember-latest.js:1271
DS.Model.Ember.Object.extend.dataDidChange ember-data-latest.js:3128
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
notifyObservers ember-latest.js:1872
Ember.notifyObservers ember-latest.js:1999
propertyDidChange ember-latest.js:2632
Ember.Observable.Ember.Mixin.create.propertyDidChange ember-latest.js:7917
Ember.Observable.Ember.Mixin.create.notifyPropertyChange ember-latest.js:7930
didChangeData ember-data-latest.js:2053
Ember.StateManager.Ember.State.extend.sendRecursively ember-latest.js:15446
Ember.StateManager.Ember.State.extend.send ember-latest.js:15431
DS.Model.Ember.Object.extend.send ember-data-latest.js:3058
DS.Store.Ember.Object.extend.load ember-data-latest.js:1737
DS.Store.Ember.Object.extend.loadMany ember-data-latest.js:1763
embeddedFindRecord ember-data-latest.js:3434
hasAssociation ember-data-latest.js:3459
ComputedPropertyPrototype.get ember-latest.js:2968
get ember-latest.js:1362
getPath ember-latest.js:1484
get ember-latest.js:1355
getWithGlobals ember-latest.js:4041
Binding.connect ember-latest.js:4140
connectBindings ember-latest.js:4600
finishPartial ember-latest.js:4610
Class ember-latest.js:8315
Ember.Mixin.create.create ember-latest.js:8457
Ember.View.Ember.Object.extend.createChildView ember-latest.js:13179
Ember.View.states.inBuffer.appendChild ember-latest.js:13622
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19043
(anonymous function) ember-latest.js:19208
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
program2
(anonymous function) handlebars-1.0.0.beta.6.js:1529
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember._HandlebarsBoundView.Ember._MetamorphView.extend.render ember-latest.js:18075
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
bind ember-latest.js:18129
(anonymous function) ember-latest.js:18199
(anonymous function) ember-latest.js:18271
program1
(anonymous function) handlebars-1.0.0.beta.6.js:1529
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14078
Ember.View.Ember.Object.extend.forEachChildView ember-latest.js:12486
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14077
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19043
(anonymous function) ember-latest.js:19208
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14078
Ember.View.Ember.Object.extend.forEachChildView ember-latest.js:12486
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14077
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19624
(anonymous function) ember-latest.js:18167
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.Ember.Object.extend.createElement ember-latest.js:12669
Ember.View.states.preRender.insertElement ember-latest.js:13558
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
invoke ember-latest.js:3428
iter ember-latest.js:3475
RunLoop.flush ember-latest.js:3531
RunLoop.end ember-latest.js:3447
Ember.run.end ember-latest.js:3639
autorun ember-latest.js:3705

Thanks for any help.

谢谢你的帮助。

Update:This fiddleworks (with example from docs), but how could those objects be represented if the tags aren't real models (i.e. don't have IDs)?

更新:这个小提琴有效(以docs为例),但是如果标签不是真实模型(即没有 ID),如何表示这些对象?

回答by Jorgeblom

Well... It was a little bit difficult but mixing all answers in this post I made it work.

嗯......这有点困难,但在这篇文章中混合了所有答案,我使它起作用。

Firstly, you should create a transform for the new type "array":

首先,您应该为新类型“数组”创建一个转换:

DS.ArrayTransform = DS.Transform.extend({
  deserialize: function(serialized) {
    return (Ember.typeOf(serialized) == "array")
        ? serialized 
        : [];
  },

  serialize: function(deserialized) {
    var type = Ember.typeOf(deserialized);
    if (type == 'array') {
        return deserialized
    } else if (type == 'string') {
        return deserialized.split(',').map(function(item) {
            return jQuery.trim(item);
        });
    } else {
        return [];
    }
  }
});

App.register("transform:array", DS.ArrayTransform);

Now, in your model, just use it as another attr:

现在,在您的模型中,只需将其用作另一个属性:

App.myModel = Ember.Model.extend({
    name : DS.attr('string'),
    cont : DS.attr('array')
}

And we are done. Remember, when adding elements to the array, to use pushObject.

我们已经完成了。请记住,向数组添加元素时,要使用 pushObject。

In a controller:

在控制器中:

this.get('model.cont').pushObject('new Item');

I hope this helps someone.

我希望这可以帮助别人。

回答by Shreyans

I use a rawtransform, which looks like this in ember-data revision 11:

我使用了一个raw转换,它在 ember-data 修订版 11 中看起来像这样:

DS.RESTAdapter.registerTransform('raw', {
    deserialize: function(serialized) {
        return serialized;
    },  
    serialize: function(deserialized) {
        return deserialized;
    }   
});

Then, within a model, I do this:

然后,在模型中,我这样做:

App.MyModel = Ember.Model.extend({
    anArray: DS.attr('raw')
});

and can use anArraylike a regular array anywhere.

并且可以anArray像常规数组一样在任何地方使用。

回答by Mayank Patel

Here is an example of creating a custom array type in Ember-Data (version 10):

以下是在 Ember-Data(版本 10)中创建自定义数组类型的示例:

DS.JSONTransforms.array =

  # If the outgoing json is already a valid javascript array
  # then pass it through untouched. In all other cases, replace it
  # with an empty array.  This means null or undefined values
  # automatically become empty arrays when serializing this type.

  serialize: (jsonData)->
    if Em.typeOf(jsonData) is 'array' then jsonData else []


  # If the incoming data is a javascript array, pass it through.
  # If it is a string, then coerce it into an array by splitting
  # it on commas and trimming whitespace on each element.
  # Otherwise pass back an empty array.  This has the effect of
  # turning all other data types (including nulls and undefined
  # values) into empty arrays.

  deserialize: (externalData)->
    switch Em.typeOf(externalData)
      when 'array'  then return externalData
      when 'string' then return externalData.split(',').map((item)-> jQuery.trim(item))
      else               return []

Now you can use the custom type in a model attribute:

现在您可以在模型属性中使用自定义类型:

App.CalenderWeek = DS.Model.extend
  selected_days = DS.attr('array')

And now when you fetch a record with:

现在,当您使用以下方法获取记录时:

App.CalendarWeek.find(1)

both of these incoming json records will deserialize correctly into an Array:

这两个传入的 json 记录都将正确反序列化为一个数组:

{ selected_days: ['Monday', 'Tuesday', 'Saturday'] }

or

或者

{ selected_days: 'Monday, Tuesday, Saturday' }

回答by Ryan

In Ember Data 1.0.0 Beta, one has been given the ability to "register" his or her custom transform "subclass". I'd prefer to refer to it as an extended DS.Transformobject.

Ember Data 1.0.0 Beta 中,人们可以“注册”他或她的自定义变换“子类”。我更愿意将它称为扩展DS.Transform对象。

DS.ArrayTransform = DS.Transform.extend({
    deserialize: function(deserialized) {
        // ...
        return deserialized;
    },

    serialize: function(serialized) {
        // ...
        return serialized;
    }
});

App.register('transform:array', DS.ArrayTransform);

回答by Mike Aski

If you absolutely need a custom data structure to be exchanged with your server, you can enrich DS.attr.transformsand declare a new arraycodec, for example.

例如,如果您绝对需要与服务器交换自定义数据结构,则可以丰富DS.attr.transforms和声明新的array编解码器。

See source codefor existing attribute codecs implementation. It is a good place to start adding your own.

请参阅现有属性编解码器实现的源代码。这是开始添加自己的好地方。

回答by Devin G Rhode

Interestingly all the other 4 answers to this question have almost identical deserialize and serialize functions, so you could simplify things down to:

有趣的是,这个问题的所有其他 4 个答案都具有几乎相同的反序列化和序列化功能,因此您可以将事情简化为:

import Em from 'ember'
import DS from 'ember-data'

# Presumably based on these answers: http://stackoverflow.com/questions/12168570/how-to-represent-arrays-within-ember-data-models
# All we need to do is always make sure an array is returned from serialize or deserialize

toArray = (data) ->
  switch Em.typeOf(data)
    when 'array'  then data
    when 'string' then JSON.parse(data)
    else []

export default DS.Transform.extend
  deserialize: toArray
  serialize: toArray

This is using ember-cli-coffees6for coffeescript with import/exportsupport

这是使用ember-cli-coffees6import/export支持咖啡脚本

回答by xiaolingxiao

A bit late to the game here but here's a jFiddle I found that is a simple implementation of declaring a new array codec

这里的游戏有点晚了,但我发现这是一个 jFiddle,它是声明新数组编解码器的简单实现

http://jsfiddle.net/Nook/ab2Xf/

http://jsfiddle.net/Nook/ab2Xf/