我目前正在开发具有两个组件的余烬应用程序。
一个组件代表地图,另一个组件代表好友列表。
两个组件都放置在相同的车把模板中。
我要实现的目标是,用户可以选中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.[]')