我通过在EmberCli中重建TodoMVC来学习余烬。我重新创建了所有的功能,但我遇到了一个问题,我希望有人可以了解情况。
当我的模型中的属性发生变化时,我的Todos ArrayController似乎会观察并触发函数,但是当我的Todo ObjectController中的值发生变化时,它不会发生。
我将isEditing移到模型中,以便在我调用editTodo
canToggle
时触发。但我更愿意将该值存储在我的控制器而不是模型中。
我使用propTest布尔值设置了一个测试。点击按钮,我点火propToggle
,但todoPropToggle
没有响应更改。爆炸的唯一时间是初始化。
任何见解都会非常有用。
TODOS CONTROLLER
import Ember from 'ember';
export default Ember.ArrayController.extend({
actions: {
createTodo: function() {
var title = this.get('newTitle');
if (!title.trim()) {
return;
}
var todo = this.store.createRecord('todo', {
title: title,
isCompleted: false,
isEditing:false
});
this.set('newTitle', '');
todo.save();
}
},
canToggle: function() {
var isEditing = this.isAny('isEditing');
return this.get('length') && !isEditing;
}.property('length','@each.isEditing'),
todoPropToggle: function() {
var hasPropTest = this.isAny('propTest');
return hasPropTest;
}.property('@each.propTest')
});
TODO CONTROLLER
import Ember from 'ember';
export default Ember.ObjectController.extend({
actions: {
editTodo: function() {
var todo = this.get('model');
todo.set('isEditing', true);
},
removeTodo: function() {
var todo = this.get('model');
todo.deleteRecord();
todo.save();
},
acceptChanges: function() {
var todo = this.get('model');
todo.set('isEditing', false);
if (Ember.isEmpty(this.get('model.title'))) {
this.send('removeTodo');
}
else {
this.get('model').save();
}
},
propToggle:function(){
this.set('propTest',!this.get('propTest'));
}
},
propTest:true,
isCompleted: function(key, value) {
var model = this.get('model');
if (value === undefined) {
return model.get('isCompleted');
}
else {
model.set('isCompleted', value);
model.save();
return value;
}
}.property('model.isCompleted')
});
答案 0 :(得分:1)
替代方法怎么样?我们可以切换' canToggle'在arrayController中直接从对象控制器使用parentController或指定需求。避免必须观察所有应该更有效的itemControllers。
TODOS CONTROLLER:
import Ember from 'ember';
export default
Ember.ArrayController.extend({
/**
* references the todo model that is currently being edited
*/
editingTodo: null,
canToggle: Ember.computed.notEmpty('editingTodo'),
actions: {
createTodo: function () {
var title = this.get('newTitle');
if (!title.trim()) {
return;
}
var todo = this.store.createRecord('todo', {
title: title,
isCompleted: false,
isEditing: false
});
this.set('newTitle', '');
todo.save();
}
}
});
TODO CONTROLLER
import Ember from 'ember';
export default
Ember.ObjectController.extend({
needs:['todos']
todos : Ember.computed.alias('controllers.todos'),
actions: {
editTodo: function () {
this.set('todos.editingTodo', this.get('model'));
},
removeTodo: function () {
var todo = this.get('model');
if (this.get('todos.editingTodo') === todo) {
this.set('todos.editingTodo', null);
}
todo.deleteRecord();
todo.save();
},
acceptChanges: function () {
this.set('todos.editingTodo', null);
if (Ember.isEmpty(this.get('model.title'))) {
this.send('removeTodo');
}
else {
this.get('model').save();
}
}
},
isCompleted: function (key, value) {
var model = this.get('model');
if (value === undefined) {
return model.get('isCompleted');
}
else {
model.set('isCompleted', value);
model.save();
return value;
}
}.property('model.isCompleted')
});
我还没有测试过,但我希望你能得到我提出的解决方案的主旨。
答案 1 :(得分:1)
propTest
看起来像是一个计算属性,而不是一个可观察的属性。 (编辑:并不是计算属性没有底层的observable为它们提供动力,但是它们的用法不同,我喜欢将它们分开)当底层propTest触发时它会触发,但如果没有变化,ember将会在运行循环中没有运行。如果您认为这是一个原始的可观察对象,请使用observes()
语法。 @each
将在这里工作,但我喜欢显式并且有一个可观察的更新它需要什么而不是使用计算属性,除非我需要直接访问该属性以在模板中绑定。
“仅执行时触发”源于创建的计算属性的初始绑定。如果它之后永远不会触发,那么您用于计算属性@each.propTest
的底层绑定必须是不正确的,否则确实会触发。
我认为您可能也会对ObjectController的目的感到困惑。 Ember.Object
可以执行控制器可以执行的所有可观察业务,而不是支持它的“模型”或“内容”属性。看起来你可能想要使用直接对象而不是控制器来处理todo,因为ember并不真正具有“模型”类型。然后我将对象本身作为ArrayController内容的一部分,此时@each将能够按照您的预期迭代它们。
ObjectController与ArrayController处于相同的使用级别。你可以像在这里做的那样嵌套它们,但是我的狡猾感觉在给应用程序这样做是错误的。您可能不需要为每个待办事项对象都有一个支持控制器,您只需要todo对象本身。