Mithril - 在 child 组件修改 parent 组件数据后,Re-sort 数组 child 组件
Mithril - Re-sort array of child components after child component modifies parent component data
如果有人能为这个问题想出更好的标题,请告诉我。
我花了很长时间才找到这个问题的答案。我敢肯定其他人也会犯同样的错误,所以我会post下面的答案。
一旦我提供了一些背景信息,这个问题就会更有意义。我有一个 parent 组件,它有一个 object 数组和匹配的键(例如 ctrl.arrayOfObjects
)。我根据每个 object(例如 ctrl.arrayOfObjects[0].keyToSortBy
)共享的键之一的值对这个数组进行排序。然后,我将 now-sorted 数组中的每个元素传递给另一个组件。
此 child 组件有一个 onclick
方法,该方法更改 parent 和 child 之间共享的数据,即 object 之一s 在 parent 的 ctrl.arrayOfObjects
中。它更改了用于对 parent 组件的 ctrl.arrayOfObjects
(例如,sharedObject.keyToSortBy
)进行排序的键的值。
我的问题是,在触发此 onclick
事件后,parent 组件 而不是 re-sort [=74 的数组=]秒。 onclick
事件 确实 修改了它应该修改的数据 (sharedObject.keyToSortBy
),我知道这是因为页面 确实 re-render sharedObject.keyToSortBy
的新值。但它 而不是 re-sort parent 组件的 ctrl.arrayOfObjects
.
奇怪的是,如果我执行 console.log
,排序方法被调用,但页面不显示任何更改。
代码如下(ctrl.arrayOfObjects
是 ctrl.jokes
):
var JokeWidgetSeries = {
controller: function() {
var ctrl = this;
ctrl.jokes = [{
text: "I'm a joke",
votes: 3
}, {
text: "This is another joke",
votes: 1
}, {
text: "A third joke",
votes: 1
}]
},
view: function(ctrl) {
return m('#jokes-container',
m('#jokes',
ctrl.jokes.sort(function(a, b) {
// Sort by number of votes.
return (a.votes < b.votes) ? 1 : (a.votes > b.votes) ? -1 : 0;
}).map(function(joke) {
// Create a 'JokeWidget' for each object in 'ctrl.jokes'.
// Share the 'joke' object with the child component.
return m.component(JokeWidget, joke);
})
)
);
}
};
var JokeWidget = {
controller: function(inherited) {
var ctrl = this;
ctrl.joke = inherited;
},
view: function(ctrl) {
return m('.joke', [
m('.joke-text', ctrl.joke.text),
m('.joke-vote-count', ctrl.joke.votes),
m('.thumb-up', {
onclick: function(e) {
// Here, the page shows that the vote count has changed,
// but the array of 'JokeWidget' DOM elements do not re-sort.
ctrl.joke.votes += 1;
}
})
]);
}
};
触发JokeWidget
组件的onclick
方法后,显示ctrl.joke.votes
的.joke-vote-count
DOM元素确实增加了1,但是确实没有像它应该的那样在页面上的 list/array 小部件中向上移动。
但是,如果我将这两个组件合二为一,数组 会 得到 re-sort,就像我想要的那样。像这样:
var JokeWidgetSeries = {
controller: function() {
var ctrl = this;
ctrl.jokes = [{
text: "I'm a joke",
votes: 3
}, {
text: "This is another joke",
votes: 1
}, {
text: "A third joke",
votes: 1
}]
},
view: function(ctrl) {
return m('#jokes-container',
m('#jokes',
ctrl.jokes.sort(function(a, b) {
// Sort by number of votes.
return (a.votes < b.votes) ? 1 : (a.votes > b.votes) ? -1 : 0;
}).map(function(joke) {
// Create a 'JokeWidget' component instance for each object in 'ctrl.jokes'.
// Share the 'joke' object with the child component.
return m('.joke', [
m('.joke-text', joke.text),
m('.joke-vote-count', joke.votes),
m('.thumb-up', {
onclick: function(e) {
// Here, the array of 'JokeWidget' DOM elements
// DO re-sort. Why?
joke.votes += 1;
}
})
]);
})
)
);
}
};
我怎样才能分离这些组件并仍然使这个 re-sorting 方法起作用?
解决方法很简单。在父子组件之间共享对象时,将对象传递给子组件的view
方法而不是controller
方法。
在 Mithril 中创建组件时,您可以将数据传递给 both controller
and view
组件的方法。此数据将是 controller
方法的第一个参数和 view
方法的第二个参数。
不是在 JokeWidget
的 controller
方法中将共享对象设置为 ctrl.joke
,然后在其 view
方法中引用它,只需将共享对象直接到 view
方法。像这样:
var JokeWidget = {
// Do not pass the object this way.
// controller: function(joke) {
// var ctrl = this;
// ctrl.joke = joke;
// },
// Pass the shared object as a second parameter to the 'view' method.
view: function(ctrl, joke) {
return m('.joke', [
m('.joke-text', joke.text),
m('.joke-vote-count', joke.votes),
m('.thumb-up', {
onclick: function(e) {
// Now, the array of 'JokeWidget' DOM elements will re-sort.
joke.votes += 1;
}
})
]);
}
};
这也删除了额外的抽象层,使其更易于阅读和理解。
如果有人能为这个问题想出更好的标题,请告诉我。
我花了很长时间才找到这个问题的答案。我敢肯定其他人也会犯同样的错误,所以我会post下面的答案。
一旦我提供了一些背景信息,这个问题就会更有意义。我有一个 parent 组件,它有一个 object 数组和匹配的键(例如 ctrl.arrayOfObjects
)。我根据每个 object(例如 ctrl.arrayOfObjects[0].keyToSortBy
)共享的键之一的值对这个数组进行排序。然后,我将 now-sorted 数组中的每个元素传递给另一个组件。
此 child 组件有一个 onclick
方法,该方法更改 parent 和 child 之间共享的数据,即 object 之一s 在 parent 的 ctrl.arrayOfObjects
中。它更改了用于对 parent 组件的 ctrl.arrayOfObjects
(例如,sharedObject.keyToSortBy
)进行排序的键的值。
我的问题是,在触发此 onclick
事件后,parent 组件 而不是 re-sort [=74 的数组=]秒。 onclick
事件 确实 修改了它应该修改的数据 (sharedObject.keyToSortBy
),我知道这是因为页面 确实 re-render sharedObject.keyToSortBy
的新值。但它 而不是 re-sort parent 组件的 ctrl.arrayOfObjects
.
奇怪的是,如果我执行 console.log
,排序方法被调用,但页面不显示任何更改。
代码如下(ctrl.arrayOfObjects
是 ctrl.jokes
):
var JokeWidgetSeries = {
controller: function() {
var ctrl = this;
ctrl.jokes = [{
text: "I'm a joke",
votes: 3
}, {
text: "This is another joke",
votes: 1
}, {
text: "A third joke",
votes: 1
}]
},
view: function(ctrl) {
return m('#jokes-container',
m('#jokes',
ctrl.jokes.sort(function(a, b) {
// Sort by number of votes.
return (a.votes < b.votes) ? 1 : (a.votes > b.votes) ? -1 : 0;
}).map(function(joke) {
// Create a 'JokeWidget' for each object in 'ctrl.jokes'.
// Share the 'joke' object with the child component.
return m.component(JokeWidget, joke);
})
)
);
}
};
var JokeWidget = {
controller: function(inherited) {
var ctrl = this;
ctrl.joke = inherited;
},
view: function(ctrl) {
return m('.joke', [
m('.joke-text', ctrl.joke.text),
m('.joke-vote-count', ctrl.joke.votes),
m('.thumb-up', {
onclick: function(e) {
// Here, the page shows that the vote count has changed,
// but the array of 'JokeWidget' DOM elements do not re-sort.
ctrl.joke.votes += 1;
}
})
]);
}
};
触发JokeWidget
组件的onclick
方法后,显示ctrl.joke.votes
的.joke-vote-count
DOM元素确实增加了1,但是确实没有像它应该的那样在页面上的 list/array 小部件中向上移动。
但是,如果我将这两个组件合二为一,数组 会 得到 re-sort,就像我想要的那样。像这样:
var JokeWidgetSeries = {
controller: function() {
var ctrl = this;
ctrl.jokes = [{
text: "I'm a joke",
votes: 3
}, {
text: "This is another joke",
votes: 1
}, {
text: "A third joke",
votes: 1
}]
},
view: function(ctrl) {
return m('#jokes-container',
m('#jokes',
ctrl.jokes.sort(function(a, b) {
// Sort by number of votes.
return (a.votes < b.votes) ? 1 : (a.votes > b.votes) ? -1 : 0;
}).map(function(joke) {
// Create a 'JokeWidget' component instance for each object in 'ctrl.jokes'.
// Share the 'joke' object with the child component.
return m('.joke', [
m('.joke-text', joke.text),
m('.joke-vote-count', joke.votes),
m('.thumb-up', {
onclick: function(e) {
// Here, the array of 'JokeWidget' DOM elements
// DO re-sort. Why?
joke.votes += 1;
}
})
]);
})
)
);
}
};
我怎样才能分离这些组件并仍然使这个 re-sorting 方法起作用?
解决方法很简单。在父子组件之间共享对象时,将对象传递给子组件的view
方法而不是controller
方法。
在 Mithril 中创建组件时,您可以将数据传递给 both controller
and view
组件的方法。此数据将是 controller
方法的第一个参数和 view
方法的第二个参数。
不是在 JokeWidget
的 controller
方法中将共享对象设置为 ctrl.joke
,然后在其 view
方法中引用它,只需将共享对象直接到 view
方法。像这样:
var JokeWidget = {
// Do not pass the object this way.
// controller: function(joke) {
// var ctrl = this;
// ctrl.joke = joke;
// },
// Pass the shared object as a second parameter to the 'view' method.
view: function(ctrl, joke) {
return m('.joke', [
m('.joke-text', joke.text),
m('.joke-vote-count', joke.votes),
m('.thumb-up', {
onclick: function(e) {
// Now, the array of 'JokeWidget' DOM elements will re-sort.
joke.votes += 1;
}
})
]);
}
};
这也删除了额外的抽象层,使其更易于阅读和理解。