Skip to main content
 首页 » 编程设计

带有 knockout 功能的 jQuery 表排序器之添加行

2026年07月24日10kevingrace

我正在尝试将 tablesorter 与 savesort 小部件一起使用。该表由 knockout 填充。

第一次填充表时,我得到了正确的行数,并且它会记住排序。然后,我使用 ajax 并绑定(bind)到 knockout 数组,用数据重新填充表。然后数据加倍,但 knockout (正确)仅跟踪一半的数据。

到目前为止,我已经追踪到当我在此方法中应用保存的排序时:

self.tablesorter = function () { 
                        $('table.tablesorterTranslation').trigger("update"); 
                        setTimeout(function () { 
                            var sl = $.tablesorter.storage($('table.tablesorterTranslation'), 'tablesorter-savesort'); 
                            var sortList = (sl && sl.hasOwnProperty('sortList') && $.isArray(sl.sortList)) ? sl.sortList : ''; 
                            if (sortList && sortList.length > 0) { 
                                // update sort change 
                                $('table.tablesorterTranslation').trigger("sorton", [sortList]); 
                            } 
                        }, 1000); 
                        return false; 
                    }; 

此方法由 knockout 操作后绑定(bind)调用。

在调用该方法之前,我对于 knockout 数组中的每个项目都有一个表行,在执行后,我有两个,一个由 knockout 跟踪,另一个似乎由表排序器添加。

这是由于表排序器缓存值造成的吗?有没有办法清理它?

HTML:

    <table class="tablesorterTranslation" data-bind="visible: contents().length > 0"> 
                <colgroup> 
                    <col class="referencenumber"/> 
                    <col class="title"/> 
                </colgroup> 
                <thead> 
                    <tr> 
                        <th class="referencenumber">Ref number</th> 
                        <th class="title">Title</th> 
                    </tr> 
                </thead> 
                <tbody data-bind="foreach: contents, postAction: tablesorter(), visible: contents().length > 0"> 
                    <tr> 
                        <td class="referencenumber"> 
                            <span data-bind="text: contentReferenceNumber"></span> 
                        </td> 
                        <td class="title"> 
                            <a data-bind="attr: {href: previewUrl, title: previewTitle}, click: previewpopup" class="preview_translation"><%: AdminResources.Menu_Preview %></a> 
                      </td> 
                </tr> 
            </tbody> 
        </table> 

重新填充表格的ajax:

self.setContentList = function () { 
                        if ($('#LanguageIdNameValuePairs option').length > 0) { 
                            self.contents.removeAll(); 
                            self.loading(true); 
                            $.ajax('<%= Url.Action("GetContentList", "TranslateContentMenu") %>', 
                                { 
                                    dataType: 'json', 
                                    data: { 
                                        languageId: $('#LanguageIdNameValuePairs').val(), 
                                        page: self.page 
                                    }, 
                                    success: function (allData) { 
                                        var mappedContent = $.map(allData, function (item) { return new ContentViewModel(item); }); 
                                        self.loading(false); 
                                        self.contents(mappedContent); 
                                    } 
                                }); 
                        } else { 
                            self.contents(new Array()); 
                        } 
                    }; 

内容 View 模型:

(function (ko) { 
    PODIUM.translation.ContentViewModel = function(data) { 
        this.contentReferenceId = ko.observable(data.contentReferenceId); 
        this.contentName = data.contentName; 
        this.previewUrl = ko.observable(data.previewUrl); 
        this.previewTitle = ko.observable(data.previewTitle); 
        this.publishTitle = ko.observable(data.publishTitle); 
        this.contentReferenceNumber = ko.observable(data.contentReferenceNumber); 
    }; 
}(ko)); 

最后,使用保存排序填充表并定义表排序(我认为保存排序是问题)。

       $('#OptionsMenu').change(function () { 
            viewModel.setContentList(); 
        }); 
        $('table.tablesorterTranslation').tablesorter({ 
            widgets: ["saveSort"], 
            widgetOptions: {} 
        }); 

我有一个选择列表,其中包含一些值,当此更改时,我从服务器获取新值并重新填充表。这是它记住旧值的地方,但我想“清理”表格并重新开始。

请您参考如下方法:

我自己找到了答案,但不是我想要的。

基本上,由于我使用的是 knockout ,所以我不应该对 View 本身进行更改,而是更改 View 模型。所以,我研究了对数组进行排序,并让 knockout 完成剩下的魔法。

我首先删除了 tablesorter 的所有痕迹(除了 table 上的 css 类,因为我已经在样式表中使用了它)。

然后我添加了这个方法:

            self.sortContents = function (element, sortProperty) { 
                var elem = $(element); 
                var direction = (elem.hasClass('headerSortDown')) ? 'headerSortUp' : 'headerSortDown'; 
                var selector = $.trim($(element).attr('class').replace('header', '').replace('headerSortUp', '').replace('headerSortDown', '')); 
                if (direction == 'headerSortUp') { 
                    self.filterStorage.updateSortFilter(selector, sortProperty); 
                    self.contents.sort(function(left, right) { 
                        return left[sortProperty] == right[sortProperty] ? 0 : (left[sortProperty] > right[sortProperty] ? -1 : 1); 
                    }); 
                    elem.removeClass('headerSortDown'); 
                    elem.addClass('headerSortUp'); 
                } else { 
                    self.filterStorage.updateSortFilter(selector, sortProperty); 
                    self.contents.sort(function (left, right) { 
                        return left[sortProperty] == right[sortProperty] ? 0 : (left[sortProperty] < right[sortProperty] ? -1 : 1); 
                    }); 
                    elem.removeClass('headerSortUp'); 
                    elem.addClass('headerSortDown'); 
                } 
            }; 

请注意,我使用与 tablesort 插件相同的 css 类,这是因为 tablesorter 已在应用程序的其他位置使用,并且这些类的 css 已存在。

我将表头更改为:

<th class="title header" data-bind="click: function(data, event){ return sortContents($(event.target), 'contentName')}"><%: AdminResources.ContentOverview_Title %></th> 

然后,由于我在困惑中起床,试图保存排序状态,所以我必须为此想出一些办法。所以我创建了一个新类,其中包含方法、更新和获取。这保存了我排序的标题和方向。

function getSortFilter() { 
    var cookie = $.cookie(tableSortedByCookie); 
    return JSON.parse(cookie); 
} 
function updateSortFilter(selector, property) { 
    $.cookie(tableSortedByCookie, null); 
    $.cookie(tableSortedByCookie, JSON.stringify({ selector: selector, property: property }), { path: '/' }); 
} 

你可以在sortcontents方法中看到update的用法。 (此方法位于包含表的页面的 View 模型上)。

然后我将其添加到 ajax 成功方法的底部:

var tableSortCookie = self.filterStorage.getSortFilter(); 
if (tableSortCookie != null && tableSortCookie.selector != null) { 
   var header = $('.tablesorterTranslation th.' + tableSortCookie.selector); 
   self.sortContents(header, tableSortCookie.property); 
} 

然后,我能够使用 knockout 对数据进行排序,以及存储状态并在更改数据和刷新页面时加载状态。