【问题标题】:Emberjs - modifying arrayEmberjs - 修改数组
【发布时间】:2014-06-17 11:08:49
【问题描述】:

我对 Ember 有一些我不太了解的问题。我有一个这样的数组:

var device.images = [
    0: {
        url: "url",
        key: "key"
    },
    1: "url2",
    2: "url3",
    3: "url4"
];'

在我的控制器中,在地图中,我尝试修改数组中的每个项目:

device.images[idx] = image;

image 是一个新对象,看起来像我的数组的第一项。但我总是得到断言失败:

Assertion Failed: You must use Ember.set() to access this property (of [object Object]...

我该如何解决?因为这通常不应该有效?

[编辑] 这是完整的代码:

loadGallery: function( device ) {

        var that = this;
        var images = device.images.map( function( item, idx ) {
            return new Ember.RSVP.Promise(function( resolve ) {
                if ( item.url ) {
                    resolve( item );
                }
                else {
                    resolve( that.imageStore.readImage( that, item ) );
                }
            })
            .then( function( image ) {
                device.images.set( idx, image );
                that.set( 'selectedItem.images', device.images );
                return image;
            });
        });
        return Ember.RSVP.Promise.all( images );
    },

【问题讨论】:

    标签: ember.js


    【解决方案1】:

    [编辑:第一次尝试错误]

    看来您应该可以使用item[index] = value 构造。用法示例:

    App.IndexRoute = Ember.Route.extend({
      resolveImage: function (that, item) {
        return {
          url: item,
          key: "resolved"
        };
      },
      model: function() {
        var device = {
          images: [
            {url: "a", key: "existing"},
            "b",
            "c"
          ]
        };
        var that = this;
        var images = device.images.map(function(item, idx) {
          return new Ember.RSVP.Promise(function(resolve) {
            if (item.url) {
              resolve(item);
            }
            else {
              resolve(that.resolveImage(that, item));
            }
          })
          .then(function(image) {
            device.images[idx] = image;
            return image;
          });
        });
        return Ember.RSVP.hash({
          model: Ember.RSVP.Promise.all(images),
          device: device
        });
      },
      setupController: function (c, m) {
        c.set("model", m.model);
        c.set("device", m.device);
      }
    });
    
      <script type="text/x-handlebars" data-template-name="index">
      <h2>From model</h2>
      <ul>
        {{#each item in model}}
          <li>{{item.url}} - {{item.key}}</li>
        {{/each}}
      </ul>
      <h2>From device</h2>
      <ul>
        {{#each item in device.images}}
          <li>{{item.url}} - {{item.key}}</li>
        {{/each}}
      </ul>
      </script>
    

    JSBin here.

    除了代码中其他地方的一些错误之外,唯一剩下的解决方案是您使用的Ember.Dataimages 并不是真正的数组,而是一个仅实现一个或多个 Ember 的数组/可枚举混合的自定义类。 [...] 构造是硬编码到 javascript 中的语法糖,库作者无法覆盖。

    因为我不使用 Ember.Data,所以我帮不了你太多。您可以尝试使用来自Ember.MutableArray 接口的显式数组变异方法。例如:

    device.images.replace(idx, 1, [image]);
    

    或者,使用object.set(key, value) 构造(我的第一个建议),但需要注意的是键值必须是字符串。例如:

    device.images.set(String(idx), image);
    

    如果这些都不起作用,您可以尝试构建一个新数组,而不是替换现有数组的成员。

    【讨论】:

    • 我试过这个,但我得到了Error: Assertion Failed: Error: Assertion Failed: Cannot call set with 0 key.。我的 idx 是我的地图的迭代(我已经编辑了主帖)。这应该可行...:/另外,设备只是从点击事件中检索的一些数据(例如,用户点击了哪个设备)。
    • 嗯,再看一遍,好像用普通数组应该可以用array[x] = y构造。 JSBin。在您的情况下,device.images 到底是什么?
    • 我在我的模型中加载了一个产品列表,每个产品都有一些信息和一组带有 url 的图像。当用户点击一个产品时,它会触发我的处理程序{{action 'selectDevice' device}},它将发送被点击设备的对象。因此,基本上,设备是一个对象,而 device.images 是设备对象中的一个数组。我只需要用一个对象替换数组的每个项目。
    • 已编辑答案,假设您使用的是 Ember.Data。无法在 jsbin 中复制您的失败状态。如果这两个想法都不起作用,请尝试将 JSBin 测试用例调整为与您遇到的相同的失败状态。
    • 是的,我正在使用 Ember-Data,device.images.set( idx+'', image); 似乎有效。但是当我做that.set( 'selectedItem.images', device.images ); 时,为什么 selectedItem 没有刷新到我的模板中?我已经调试了devices.images,现在里面的数据是正确的。
    猜你喜欢
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 2021-01-12
    • 2014-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多