如何提高这个js脚本的性能(函数调用指数增加)?

时间:2010-11-26 14:43:31

标签: javascript jquery

如何增加像这样的longish js代码的任何一般提示?它工作得很好,但有时它会变得有点迟钝,所有的拖放和ajax功能都会变慢。

我知道这段代码有点长,所以我不是在寻找具体的建议。快速浏览一下这段代码后,您的第一个想法。

编辑:

我发现了一件非常可怕的事情。对$('。folderListOnclick')。click事件的dragDrop()调用呈指数增长。每次点击后,dragDrop()被调用1次,2次,4次,8次。这就是放慢速度的原因。

但我不明白为什么会这样。

<script type="text/javascript">
    //<!--
$(document).ready(function() {

    function in_array (needle, haystack, argStrict) {
        var key = '', strict = !!argStrict; 
        if (strict) {
            for (key in haystack) {
                if (haystack[key] === needle) {
                    return true;            }
            }
        } else {
            for (key in haystack) {
                if (haystack[key] == needle) {
                    return true;
                }
            }
        }
         return false;
    }

    var openedFolders = new Array();

    var start = 0;
    var stop = 0;
    $('.drag').each(function() {
        var draggables = $(this).parents('table').find('.drag');
        var $next = draggables.filter(':gt(' + draggables.index(this) + ')').first();
        var width = $(this).css('width');
        var nextWidth = $next.css('width');
        if (nextWidth > width /*&& 30 == parseInt(width)*/) {
            $(this).removeClass('ordinaryFolderClosed');
            $(this).removeClass('ordinaryFolderOpened');
            if (in_array($(this).attr('rel'), openedFolders)) {
                $(this).addClass('ordinaryFolderOpened');
            } else {
                $(this).addClass('ordinaryFolderClosed');
            }               
        }
        if (in_array($(this).attr('rel'), openedFolders)) {
            start = 1;
        }
        if (1 == start && stop < 2) {               
            if (30 == parseInt(width)) {
                stop++;
            }
        } else {
            start = 0;
            stop = 0;
            if (parseInt(width) > 30) {
                $(this).parent().parent().hide();
            }
        }
    });

    function dragDrop()
    {       
        $('.folders .trow1').hover(
            function () {
                if ($(this).css('backgroundColor') != 'rgb(52, 108, 182)' && $(this).css('backgroundColor') != '#346cb6') {
                    $(this).css('background', "#C2E3EF");
                }
            },
            function () {
                if ($(this).css('backgroundColor') != 'rgb(52, 108, 182)' && $(this).css('backgroundColor') != '#346cb6') {
                    $(this).css('background', 'transparent');   
                }
            }
        );

        $('.drag').click(function() {

            if ($(this).hasClass('noclick')) {
                $(this).removeClass('noclick');
            } else {

                var draggables = $(this).parents('table').find('.drag');
                var $next = draggables.filter(':gt(' + draggables.index(this) + ')').first();
                var width = $(this).css('width');
                var nextWidth = $next.css('width');
                if (nextWidth > width /*&& 30 == parseInt(width)*/) {
                    var isVisible = $next.is(':visible');
                    if (isVisible) {
                        $(this).removeClass('ordinaryFolderClosed');
                        $(this).removeClass('ordinaryFolderOpened');
                        $(this).addClass('ordinaryFolderClosed');
                    } else {
                        $(this).removeClass('ordinaryFolderClosed');
                        $(this).removeClass('ordinaryFolderOpened');
                        $(this).addClass('ordinaryFolderOpened');
                    }
                    clickedId = $(this).attr('rel');
                    clickedId = clickedId.split(',');
                    clickedType = clickedId[1];
                    clickedId = clickedId[0];
//                  $.ajax({
//                      type:    'POST',
//                      url:     'body/obsah/mediaManager/setOpenedFolder.php',
//                      data:    'id='+clickedId+'&type='+clickedType,
//                      success: function(msg){
//                          //alert(msg);
//                      }
//                  });
                    var start = 0;
                    var stop = 0;
                    var i = 0;
                    // close folder
                    if (isVisible) {
                        $('.drag').each(function() {
                            if (0 == start) {
                                iteratedId = $(this).attr('rel');
                                iteratedId = iteratedId.split(',');
                                iteratedId = iteratedId[0];
                                if (iteratedId == clickedId) {
                                    start = 1;
                                }
                            }
                            if (1 == start && stop < 2) {
                                if ($(this).css('width') > width) {
                                    $(this).parent().parent().hide();
                                    if ($(this).hasClass('ordinaryFolderClosed') || $(this).hasClass('ordinaryFolderOpened')) {
                                        $(this).removeClass('ordinaryFolderClosed');
                                        $(this).removeClass('ordinaryFolderOpened');
                                        $(this).addClass('ordinaryFolderClosed');
                                    }
                                } else {
                                    stop++;
                                }
                            }
                            i++;
                        }); 
                    }
                    // open folder
                    else {
                        $('.drag').each(function() {
                            if (0 == start) {
                                iteratedId = $(this).attr('rel');
                                iteratedId = iteratedId.split(',');
                                iteratedId = iteratedId[0];
                                if (iteratedId == clickedId) {
                                    start = 1;
                                }
                            }
                            if (1 == start && stop < 2) {
                                if (parseInt($(this).css('width')) == parseInt(width)+5) {
                                    $(this).parent().parent().show();                   
                                }

                                if (parseInt($(this).css('width')) == parseInt(width)) {
                                    stop++;
                                }
                            }
                            i++;
                        });
                    }
                }

            }
        });

        var dragId = 0;
        var dragType = 0;
        var dropId = 0;
        var dropType = 0;
        var isFile = false; 

        $('.drag').draggable({ 
            revert: true,
            cursorAt: {top: 0, left: 0},
            drag: function() {
                if ($(this).attr('rel') !== undefined) {
                    dragId = $(this).attr('rel');
                    dragId = dragId.split(',');
                    dragType = dragId[1];
                    dragId = dragId[0];
                }
                isFile = false;
            },
            start: function(event, ui) {
                 $(this).addClass('noclick');
            }
        });

        $('.drag2').draggable({
            revert: true,
            cursorAt: {top: 0, left: 0},
            drag: function() {
                if ($(this).attr('rel') !== undefined) {
                    dragId = $(this).attr('rel');
                    dragId = dragId.split(',');
                    dragType = dragId[1];
                    dragId = dragId[0];
                }
                isFile = true;
            }
        });     

        $('.drop').droppable({
            tolerance: 'pointer',
            drop: function() {
                if ($(this).attr('rel') !== undefined) {
                    dropId = $(this).attr('rel');
                    dropId = dropId.split(',');
                    dropType = dropId[1];
                    dropId = dropId[0];
                    if (dropId != dragId) {
                        if (false == isFile) {
                            $.ajax({
                                type:    'POST',
                                url:     'body/obsah/mediaManager/folder_move.php',
                                data:    'nid='+dragId+'&pid='+dropId+'&ft='+dropType,
                                success: function(msg){
                                    ajaxElementCall('left1', 'body/obsah/mediaManager/folder_list.php?type=1', 'right1', 'body/obsah/mediaManager/file_list.php?type=1&browse=0&assignType=0&CKEditorFuncNum=0&idFolder=0');
                                    dragDrop();
                                }
                            });
                        } else if (true == isFile) {
                            $.ajax({
                                type:    'POST',
                                url:     'body/obsah/mediaManager/file_move.php',
                                data:    'fid='+dragId+'&did='+dropId+'&ft='+dropType,
                                success: function(msg){
                                    ajaxElementCall('right1', 'body/obsah/mediaManager/file_list.php?type=1&browse=0&assignType=0&CKEditorFuncNum=0&idFolder=0&reloadTree=0');
                                    dragDrop();
                                }
                            });
                        }
                    }
                }           
            }
        });

    }

    dragDrop();

    $('.folderListOnclick').click(function() {
        var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0&reloadTree=0';
        ajaxElementCall('right1', 'body/obsah/mediaManager/file_list.php?type=1&'+append);
        dragDrop();
        $('.trow1').css('background', 'transparent');
        $('.trow1').css('color', '#3e4245');
        $(this).parent().css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
        $(this).parent().css('color', 'white');
    });

    $('.folderEditOnclick').click(function() {
        var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0';
        showModal('modal_div', 'Editácia adresára'); 
        ajaxElementCall('modal_div', 'body/obsah/mediaManager/folder_edit.php?kam=edit1&'+append);
    });

    $('.folderDeleteOnclick').click(function() {
        var append = 'idFolder='+$(this).attr('rel')+'&browse=0&assignType=0&CKEditorFuncNum=0';
        showModal('modal_div', 'Vymazanie adresára'); 
        ajaxElementCall('modal_div', 'body/obsah/mediaManager/folder_delete.php?kam=del1&'+append);
    });

    $('.addNewFolder').click(function() {
        showModal('modal_div', 'Nový adresár');
        var id = '0';
        $('.folders .trow1').each(function() {
            if ($(this).css('backgroundColor') == 'rgb(52, 108, 182)' || $(this).css('backgroundColor') == '#346cb6') {
                id = $(this).attr('rel');
                id = id.split(',');
                id = id[0];
            }
        });
        ajaxElementCall('modal_div', '/body/obsah/mediaManager/folder_add.php?type=1&kam=new1&idFolder='+id+'&browse=0&assignType=0&CKEditorFuncNum=0');
    });

});    //-->

</script>

5 个答案:

答案 0 :(得分:2)

首先,应更改所有$(this)以使用变量。

var me = $(this); 

me.XXX

$(this)是一个方法调用,它无需在同一个对象上反复调用它。

这需要按块进行,因为这将是每个块中的不同对象;)

答案 1 :(得分:2)

您还没有发布任何HTML标记,也没有发布“ajaxElementCall”函数的详细信息。因此,很难确切地说你应该如何解决这个问题。但是,在每次“drop”事件中,您最终都会再次调用“dragDrop()”设置函数。你说“ajaxElementCall”会重新加载页面的某些部分,但是你的“dragDrop()”代码总是会在页面上的所有“。drag”和“。drop”元素上安装新的事件处理程序。如果“ajaxElementCall”仅更新页面的 part ,则所有未更改的“.drag”和“。drop”元素将获得额外的事件处理程序。

当您为某个选择器调用.click().hover()时,jQuery 会添加您提供给已注册的处理程序集的事件处理程序。因此,因为每次调用“dragDrop()”时都会注册新的事件处理程序,所以会越来越多地堆积起来。当事件发生时,将会运行所有这些处理程序。

您可能需要做的是更改“dragDrop()”,以便您可以告诉它只对页面的特定部分进行操作。或者,或者当它运行时,它应该“标记”它影响的每个元素,然后在应用新的事件处理程序之前检查该标记。这样它只会影响新加载的代码。 (然而,缩小搜索范围会更有效;表达式$('.drag')可能必须通过查看页面上的每个DOM元素,因此最好使用更精确的内容反正。)

答案 2 :(得分:1)

$(this)这样的查找操作非常昂贵。你最好存储和寻址对象引用;在类似的情况下,它对我帮助很大。

答案 3 :(得分:1)

它不会那么快,但这会加快几毫秒: 您应该重用一个jquery实例而不是生成一个新实例(这需要一些时间)。

示例:而不是

$(this).parent().css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
$(this).parent().css('color', 'white');

使用

var this_parent = $(this).parent();
this_parent.css('background', "#346cb6 url('img/menuButtonOver.png') left top repeat-x");
this_parent.css('color', 'white');

答案 4 :(得分:0)

可以显着优化上述代码的一件事是将in_array函数和opensFolders数组替换为一个充当字典并且效率更高的JS对象。 Decleration:

openedFolders={};

将新文件夹添加到已打开的文件夹对象:

openedFolders[folderName]=valueRelatedToTheFolderIfYouHaveOneOrWhatEver; // :)

搜索已打开的文件夹:

if(openedFolders.hasOwnProperty(folderName)){/*folderName is open*/}
相关问题