我目前正在开发一个 ember 应用程序,它有两个组件。
一个组件代表一张 map ,另一个组件代表一个好友列表。
两个组件都放置在同一个 Handlebars 模板中。
我试图实现的是,用户可以选中friendslist组件中的复选框,并在下一步中从facebook异步加载他或她的帖子(好友本身已经加载到beforeModel钩子(Hook)中)。这些异步加载的帖子应附加到模型中已存在的 friend 对象中。之后, map 组件应该收到有关更改的通知并刷新自身或调用将在 map 上绘制点的函数。
目前,我正在尝试设置单个 friend 的选中属性(这与附加帖子的方法相同,但现在会更容易):
// 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);
}
}
});
返回 Controller
actions: {
changeFriendCheckedStatus(friendEntry) {
ic.ajax.request(API.HOST + '/someUrlForPosts/' + friendEntry.get('id)).then(givenFriendPosts => {
entry.get('posts').pushObjects(givenFriendPosts);
})
}
}
如果我理解正确的话,你有 2 个模特是我的 friend 和帖子 (DS.belongsTo('friend'))。您需要将两者封装到friendEntry (friend, posts) 中。
所以你的 map 小部件也会像这样 {{map-widgetfriendEntries=friendEntries}}
您可以像这样封装它们,而不是在模型中查询帖子。
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.[]')
关于javascript - 如何在组件的复选框更改时异步加载数据并将其附加到模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37701422/