javascript - 如何优化 RadComboBox clearItems 函数

标签 javascript jquery telerik telerik-combobox

我有一个MultiSelectDropDown,也就是几个RadComboBox控件组合使用。例如,我可以有一个区域下拉列表,另一个用于仓库,另一个用于用户。这个想法是每当在较高级别上选择或取消选择项目时动态更改较低级别的内容。问题是,在选择很多项目的情况下,由于某些 Telerik functions,这会变得非常慢,但我不明白为什么。这是 MultiSelectDropDown 原型(prototype)客户端的一个 block :

changeLowerLevels: function (valueIndex, values, value) {
    if (!this.canChange) return;
    //Get selected values from combobox
    var combo = $find(this.ddlIDs[valueIndex - 1]);
    var cbItems = combo.get_checkedItems();
    var selectedItems = [];
    var change = null;
    var counter = 0;
    if (cbItems.length) this.filterString = "";
    for (var i = 0; i < cbItems.length; i++) {
        counter++;
        if (this.filterString == "") this.filterString = cbItems[i].get_text();
        selectedItems.push(cbItems[i].get_value());
    }
    if (counter > 1) this.filterString += " with " + (counter - 1) + " other" + ((counter > 2) ? "s" : "");
    if (JSON.stringify(selectedItems) === JSON.stringify(this.selectedItems[valueIndex - 1]) || selectedItems == [])
        return;
    this.selectedItems[valueIndex - 1] = selectedItems;

    var controlObject = this;
    var combo = $find(this.ddlIDs[valueIndex]);
    var comboItems = combo.get_items();
    if(!this.disabled) combo.enable();
    combo.clearItems();

    if (valueIndex == 1) this.twoLevelCache = values;
    var val = values;

    //break if all items are found
    var nrOfSelectedItems = this.selectedItems[valueIndex - 1].length;
    var nrOfFoundItems = 0;
    var index = 0;
    var indexes = [];
    var found = false;
    while (nrOfFoundItems < nrOfSelectedItems && val[index] !== undefined) {
        found = (this.selectedItems[valueIndex - 1].indexOf(val[index].Value) != -1);
        if (!(found))
            index++;
        else {
            indexes.push(index)
            nrOfFoundItems++;
            index++;
        }
    }

    //separators from valuesIndex - 1 level
    var controlObject = this;
    for (var i = 0; i < indexes.length; i++) {
        var separator = new Telerik.Web.UI.RadComboBoxItem();
        separator.set_text("<span><a class=\"checkAll tt-multi-uncheck-icon\" index=\"" + index + "\">U</a>" + $find(this.ddlIDs[valueIndex - 1]).findItemByValue(val[indexes[i]].Value).get_text() + "</span>");
        separator.set_value("");
        separator.set_isSeparator(true);
        comboItems.add(separator);
        this.twoLevelCache.push(val[indexes[i]].Levels);

        //valuesIndex level
        var valuesArray = val;
        var comboItem = new Telerik.Web.UI.RadComboBoxItem();
        for (var depot in valuesArray[indexes[i]].Levels) {
            comboItem = new Telerik.Web.UI.RadComboBoxItem();
            comboItem.set_text(valuesArray[indexes[i]].Levels[depot].Name);
            comboItem.set_value(valuesArray[indexes[i]].Levels[depot].Value);
            comboItems.add(comboItem);
            comboItem = null;
        }

        $('#' + this.ddlIDs[valueIndex] + '_DropDown a.checkAll').unbind().on("click", function () {
            checkAllLowerItems(this, controlObject.ddlIDs[valueIndex]);
        });
    }
    combo.set_emptyMessage(this.allText);
    //$("#" + this.ddlIDs[valueIndex]).html(returnValue);
    if (this.ddlIDs.length > valueIndex + 1) {
        var paramToPass = (((val == undefined) || (val[index] === undefined)) ? ("") : (val[index]));
        if (this.allText.length > 0)
            this.changeLowerLevels(valueIndex + 1, paramToPass, "");
        else {
            if (paramToPass !== "")
                paramToPass = paramToPass.Levels;
            if ((val[index] == undefined) || (val[index].Levels[0] === undefined) || (val[index].Levels[0].Value === "")) {
                this.changeLowerLevels(valueIndex + 1, paramToPass, "");
            }
            else {
                this.changeLowerLevels(valueIndex + 1, paramToPass, val[index].Levels[0].Value);
            }
        }
    }
    else {
        if (this.allText.length > 0)
            this.selectedItems[valueIndex] = "";
        else
            if ((val[index] == undefined) || (val[index].Levels[0] === undefined) || (val[index].Levels[0].Value === "")) {
                this.selectedItems[valueIndex] = "";
            }
            else {
                this.selectedItems[valueIndex] = val[index].Levels[0].Value;
            }
    }

    this.setText();
}

combo.clearItems() 非常慢。我看一下它是如何实现的:

function (){var f=this._parent._getControl();?if(f._checkBoxes){f._checkedIndicesJson="[]";?f._checkedIndices=[];?var g=f.get_items();?for(var d=0,e=g.get_count();?d<e;?d++){var c=f.get_items().getItem(d);?c.set_checked(false);?}f.updateClientState();?}a.RadComboBoxItemCollection.callBaseMethod(this,"clear");?}

如何确保此 Javascript 函数加速?

最佳答案

我终于通过重写 Telerik 客户端功能解决了这个问题。这是一个漫长而艰难的调试过程,但它在最困难的情况下产生了巨大的性能提升。从约 30 000 毫秒到约 300 毫秒。让我们看看优化的部分:

  1. 实际重写

/* Overriding Telerik functions Start */ var overridenTelerikControls = false; function overrideTelerikFunctionalities() { if (!overridenTelerikControls) { overridenTelerikControls = true; Telerik.Web.UI.RadComboBox.prototype.clearItems = function (isMultiSelectDropDown) { this.get_items().clear(isMultiSelectDropDown); this._itemData = null; }; Telerik.Web.UI.RadComboBoxItemCollection.prototype.clear = function (isMultiSelectDropDown){ var f=this._parent._getControl(); if(f._checkBoxes){ f._checkedIndicesJson="[]"; f._checkedIndices=[]; var g = f.get_items(); for(var d=0,e=g.get_count();d<e;d++){ var c=f.get_items().getItem(d); c.set_checked(false, isMultiSelectDropDown); } if (isMultiSelectDropDown) { f._updateComboBoxText(); if (f._checkAllCheckBoxElement != null) { f._updateCheckAllState(); } } f.updateClientState(); } Telerik.Web.UI.RadComboBoxItemCollection.callBaseMethod(this, "clear"); }; Telerik.Web.UI.RadComboBoxItem.prototype.set_checked = function (d, isMultiSelectDropDown){ if(!this.get_enabled()){ return; } this._setChecked(d); var c=this.get_comboBox(); if(c){ if(d){ c._registerCheckedIndex(this.get_index()); }else{ c._unregisterCheckedIndex(this.get_index()); } if (!isMultiSelectDropDown) { c._updateComboBoxText(); } if((!isMultiSelectDropDown) && (c._checkAllCheckBoxElement!=null)){ c._updateCheckAllState(); } } }; } } /* Overriding Telerik functions End*/

我的方法是默认保留旧的工作方式,但如果传递了 isMultiSelectDropDown 参数,则以优化的方式工作。所以我们有一个开关具体化为参数,我们可以打开/关闭它。主要区别在于,旧方法是在每次选中/取消选中复选框时更改显示所选元素的标签文本。主要改进是在选中/取消选中所有复选框后进行此更改。这个极其简单的想法是性能提升背后的驱动力。

  1. 实际使用情况

    overrideTelerikFunctionalities();
    combo.clearItems(true);
    

如果功能尚未覆盖且参数为真,则此功能已被覆盖,因此选择了新方法。

  1. 测试,测试,测试

关于javascript - 如何优化 RadComboBox clearItems 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46857448/

相关文章:

c# - 如何在服务器端关闭radwindow并刷新父页面

javascript - 通过类/id 从附加元素中删除标签

javascript - 如何制作:hover appearance remain after click/focus in search bar

php - 如何动态加载已解析为 PHP 的 Javascript?

kendo-ui - 剑道 Ui 格锁柱

javascript - 如何隐藏*单个* MVC/Kendo tabstrip 选项卡?

javascript - 用 jquery 求和表中的 td 值

jquery - 使用 jQuery 模拟单击​​选择元素

javascript - 简单的 Backbone.js fiddle - 我在正确的轨道上吗?

javascript - 列表元素的 Jquery 类