我目前正在开发具有两个组件的余烬应用程序。

一个组件代表地图,另一个组件代表好友列表。

两个组件都放置在相同的车把模板中。

我要实现的目标是,用户可以选中friendslist组件中的复选框,然后在下一步中从Facebook异步加载他或她的帖子(朋友本身已经加载在beforeModel挂钩中)。这些异步加载的帖子应该附加到模型中已经存在的朋友对象上。之后,应告知地图组件有关更改的信息并刷新自身,或调用将在地图上绘制点的函数。

目前,我正在尝试设置单个朋友的checked属性(这与追加帖子的方法相同,但现在会更容易):

// index.hbs
{{map-widget posts=model.posts friends=model.friends}}
{{friends-list checkedFriend='checkedFriend' friends=model.friends}}

// friends-list.hbs (component)
<ul>
  {{#each friends as |friend|}}
    <li>
      {{input type="checkbox" id=friend.facebookID checked=friend.checked change=(action checkedFriend)}}   <p>{{friend.name}}</p>
    </li>
  {{/each}}
</ul>

// friends-list.js (component)
import Ember from 'ember';

export default Ember.Component.extend({

  actions: {
    checkedFriend: function () {
      this.sendAction('checkedFriend');
    }
  }
});

// index.js (route)
export default Ember.Route.extend(AuthenticatedRouteMixin, {
...
  model: function() {
    return Ember.RSVP.hash({
      posts: this.get('currentUserPosts'),
      friends: this.get('friends')
    });
  },

  actions: {
    checkedFriend: function () {
      // Update just the first friend here to see if the approach works
      // Get the friends array from the model
      const model = this.controller.get('model');
      const friends = model.friends;

      // Update the friend
      Ember.set(friends[0], 'checked', true);

      // Map component receives an update here,
      // but "DEPRECATION: You modified (mut model.friends) twice in a single render." warning occurs
      this.set('friends', friends);
    }
  }
})


当前的方法或多或少起作用。但是,我收到的折旧警告是我在单个渲染中两次修改了模型,我认为这是从我的角度出发不良设计的标志。

我想知道的是完成上述任务的一种好方法。如果我已经走对了路,那么如果有人能告诉我为什么会出现这种双重渲染错误,我将非常高兴。

核心问题是如何正确更新模型,以及如何通知组件(尤其是未对更改设置操作的组件)以便刷新这些组件。

先感谢您。

最佳答案

您可以创建一个类-FriendEntry。通过调用其构造函数,您将收到FriendEntry的实例。现在,您将修改实例而不是原始记录(这确实不正确)。

var FriendEntry = Ember.Object.extend({
    init: function() {
        this._super(...arguments);
        this.set('somethingFriendly', true);
    }
});

export default Ember.Controller.extend({
      friendsEntries: Ember.computed.map('model.friends', function(friend) {
          // Call the constructor
          return FriendEntry.create({
               friend: friend,
               checked: false,
               posts: []
          })
      })
});


好的,这样您的组件将看起来像这样。

{{friends-list checkedFriend='changeFriendCheckedStatus' entries=friendEntries}}


// friends-list.hbs (component)
<ul>
  {{#each entries as |entry|}}

      {{input type="checkbox" checked=entry.friend.checked change=(action checkedFriend entry)}}   <p>{{entry.friend.name}}</p>

  {{/each}}
</ul>

// friends-list.js (component)
import Ember from 'ember';

export default Ember.Component.extend({

  actions: {
    checkedFriend: function (entry) {
      this.sendAction('checkedFriend', entry);
    }
  }
});


返回控制器

actions: {
   changeFriendCheckedStatus(friendEntry) {
         ic.ajax.request(API.HOST + '/someUrlForPosts/' + friendEntry.get('id)).then(givenFriendPosts => {
              entry.get('posts').pushObjects(givenFriendPosts);
         })
   }
}


如果我正确理解,您有2个我的朋友模型和帖子(DS.belongsTo('friend'))。您将需要将它们都封装到friendEntry(朋友,帖子)中。

因此,您的地图小部件也将如下所示:

无需查询模型中的帖子,您可以像这样封装它们。

    friendsEntries: function() {
           return DS.PromiseArray.create({
                  promise: Ember.RSVP.all(this.get('model.friends')).then(friends => {
                    return friends.map(friend => {
                        return FriendEntry.create({
                          friend: friend,
                          checked: false,
                          posts: store.query('posts', { friend: friend.get('id') }
                       });
                    });
                  })
          });
   }.property('model.friends.[]')

10-08 03:10