Mithril - 在子组件修改父组件数据后重新排序子组件数组
Mithril - Re-sort array of child components after child component modifies parent component data
如果有人能为这个问题想到更好的标题,请告诉我。
经过疯狂的时间,我才想出了这个问题的答案。我相信其他人也会犯同样的错误,所以我会在下面发布答案。
一旦我提供了一些背景信息,这个问题就会更有意义。我有一个父组件,它有一个具有匹配键的对象数组(例如 ctrl.arrayOfObjects
)。我按每个对象共享的键之一的值对这个数组进行排序(例如,ctrl.arrayOfObjects[0].keyToSortBy
)。然后,我将现在排序的数组中的每个元素传递给另一个组件。
这个子组件有一个onclick
方法,它改变父组件和子组件之间共享的数据,即父组件ctrl.arrayOfObjects
中的一个对象。它更改用于对父组件的ctrl.arrayOfObjects
进行排序的键的值(例如,sharedObject.keyToSortBy
)。
我的问题是,在触发此onclick
事件后,父组件不会对对象数组进行重新排序。onclick
事件确实修改了它应该修改的数据(sharedObject.keyToSortBy
),我知道这是因为页面确实重新呈现了 sharedObject.keyToSortBy
的新值。但它不会重新排序父组件的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。但它并没有像它应该的那样在页面上的小部件列表/数组中向上移动。
但是,如果我将这两个组件合并为一个,数组确实会像我想要的那样重新排序。喜欢这个:
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;
}
})
]);
})
)
);
}
};
如何分离这些组件并仍然使这种重新排序方法起作用?
解决方案很简单。在父组件和子组件之间共享对象时,请将对象传递给子组件的view
方法,而不是controller
方法。
在 Mithril 中创建组件时,可以将数据传递给组件的controller
和view
方法。此数据将是controller
方法的第一个参数和view
方法的第二个参数。
与其将共享对象设置为ctrl.joke
JokeWidget
的controller
方法,然后在其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;
}
})
]);
}
};
这也消除了额外的抽象层,使其更易于阅读和理解。
- 当组件准备就绪时,如何在Polymer中动态注册新属性
- Ember组件'jQuery可排序的模板问题
- 使用JS或新查询对列表进行排序
- 追加新web组件时出现线程问题
- 如何避免新的角度组件写在 emca 6
- 主干中的比较器在添加新模型时需要排序调用
- 插入按字母顺序、javascript或jquery排序的新列表
- 无法从jQuery可排序列表中删除新添加的项
- 如何在 Vue.js 中保持可排序的数组和组件的顺序
- 使用“可排序”时获取新元素信息
- JavaScript 将文本框存储中的值引入数组中,创建新数组进行排序
- 在 React 中向组件添加新输入并跟踪状态
- Mithril - 在子组件修改父组件数据后重新排序子组件数组
- React Native ListView 不会在排序或检索新数据后更新
- 使用 UI 可排序,在单击按钮时根据给定值将项目移动到新位置
- AngularJS:插入新项目后对列表重新排序
- jQuery dataTable 不会对新数据进行排序
- jQuery UI 可排序在克隆和附加新的可排序列表后不会刷新
- 如何使用布局管理器重新排序/排序嵌套视图而不重新渲染
- Mithril.js:如果视图使用子组件,排序数据不会重新渲染