上下文:我有一个Web工作者,它通过Websocket从后端“订阅”数据更新,然后将其发布到通过DataTables.net呈现的视图中。为了提高效率,添加的数据作为部分记录(即,仅一行)。
由于数据已从DataTable解耦(即,它没有使用Ajax API;它基本上是JavaScript源),所以我不能只添加行并呈现表。如果触发了同一行的两次按下,我将得到重复的行。
所以,我整理了一个小插件:
$.fn.dataTable.Api.register('deDupe', function (dataSet, idColumn) {
idColumn = idColumn || 0;
var columnData = this.columns().data()[idColumn];
for(var i=0; i < dataSet.length; i++) {
var thisId = dataSet[i].id;
var matchedIndex = columnData.indexOf(thisId);
if(matchedIndex > -1) {
var matchedRow = $(this.rows().nodes()[matchedIndex]);
this.row(matchedRow).remove();
}
}
// return "this" for chaining
return this;
});
(不要嘲笑我在老式的“ for”循环中获得安慰!)
然后在使用中,我这样做:
myTable.deDupe(dataSet).rows.add(dataSet).draw();
接收数据然后更新表的方法已经有输入行,该行包含在“ dataSet”中,然后我为该列传递一个COLUMN索引,该索引旨在包含用于重复数据删除的唯一ID目的。请注意,在代码执行中,不是删除传入的重复项,而是删除上一行,然后添加传入的行。在某些情况下,该行包含更新的数据,而我实际上只关心在ID级别进行重复数据删除,而不是在内容级别进行重复数据删除……始终只是盲目地使用最新数据。
那么几个问题:
是否有更好的方法?我很想看到一种核心选择,但我没有遇到。似乎是相对常见的功能。我在这里疯了,重新发明轮子吗? (换句话说,是一个初始化选项?)
在条件检查中是否存在匹配项时,您会看到以下行:var matchedRow = $(this.rows().nodes()[matchedIndex]);
这让我感到古怪,但是我无法理解其他识别要使用的行的方法在.remove()
链中。在我的脑海中,我已经知道该行的索引,因此我认为类似matchedRow = this.rows(matchedIndex)
的方法可以工作,但是找不到或类似的方法。因此,我不仅要深入研究rows().nodes()
,而且还要将整个内容包装在jQuery中,然后再传递给.row(matchedRow)
'。似乎我已经应该可以直接访问某些东西了,所以嵌套和包裹得太紧了。
别误会我的意思;代码“有效”并修复它可能是微观优化。但这使我感到非常困惑,并给了我一些代码味道,为了维护开发人员,我希望避免这种情况。
答案 0 :(得分:1)
如您所说,这可能是微优化,但是一个选择可能是选择所有行并将它们全部删除。
$.fn.dataTable.Api.register('deDupe', function (dataSet, idColumn) {
idColumn = idColumn || 0;
// Get the possible dataSet ids into an array for easier lookup
var dsIds = dataSet.map( (d) => d.id );
// Use a function in the rows() API to obtain all rows with
// a value in the idColumn that matches one of the incoming
// ids on the dataSet
var matchedRows = this.rows( (i,r) => dsIds.indexOf(r[idColumn]) > -1 );
// Remove all of the rows at once (this could be chained to the selector above)
matchedRows.remove();
// return "this" for chaining
return this;
});