使用javascript的DOM操作挂起UI线程



我有一个页面显示了两个下拉列表,一个用于主题,另一个用于类似的课程

    <fieldset>
        <legend>Subject:</legend>
        <select id="subjectList" onchange="SetCourses()">
             <option value="">select subject</option>
             <option value="1">Html</option>
             <option value="2">Css</option>
             <option value="3">Javascript</option>
             <option value="4">Jquery</option>
             <option value="5">Php</option>
        </select>
    </fieldset>
    <fieldset>
        <legend>Courses:</legend>
        <select id="courseList">
             <option value="">select course</option>
        </select>
    </fieldset>

因此,随着主题的改变,课程下拉菜单会刷新一个庞大的课程列表(大约9000-10000条记录),就像这个一样

    function SetCourses() {
        var subject = $('#subjectList').val();
        var courseList = $('#courseList');
        var courseString = '<option value="">select course</option>';
        if (!!subject) {
            courseList.html(courseString);
        }
        else {
            $.ajax({
               url: "test.html",
               context: document.body
            }).done(function(data) {
               if(!!data) {
                  $.each(data, function(index, value) {
                     courseString += '<option value="'+value.id+'">'+value.text+'</option>'; 
                  });
                  courseList.html(courseString);   // this takes times 
               }
            });
        }
    }

问题是,当记录被写入课程下拉菜单时,需要将近10-12秒的时间,在这段时间内页面会挂起,如果在这段期间你只需要点击某个地方,那么浏览器会在更长的时间内没有响应。

我进行了调试,发现在ajax调用成功之前,页面是完美的,当它到达写数据的行时,从那时起它就冻结了UI。

那么,在不冻结UI的情况下,将如此巨大的数据写入DOM的正确方法是什么呢?

我认为对于一个下拉列表太长是不合适的,请尝试自动完成:http://jqueryui.com/autocomplete/我不认为任何用户会浏览9到1万个项目来找到他们感兴趣的课程。

至于滞后;你能做的事情是有限的,这就是极限。我看不到一个简单的优化可以修复它,这样做毫无意义,因为没有人会使用包含数千个项目的下拉列表。

你愿意吗?

您应该牢记用户。用数千个项目填充下拉列表不是一个好的用户界面设计。

更改代码,在内存中构建整个字符串,并在完成后将其添加到页面中。

编辑:在我开始编辑你的代码示例后,我对所有的括号和大括号进行了排序。我确认你的代码已经包含了我的建议。正如HMR在评论中所建议的那样,您可以尝试直接创建DOM对象,而不使用字符串中间体。

最新更新