Более быстрый способ заполнить <select>с помощью Javascript - PullRequest
14 голосов
/ 31 марта 2009

У меня есть две

В некоторых случаях во втором выборе может быть около 500 (предположительных) элементов, и обновление в IE занимает 5-10 секунд. Firefox, кажется, работает отлично.

Интересно, есть ли более быстрый способ добиться этого? В настоящее время сервер создает строку, передает ее клиенту, которая затем разбивается и добавляет каждый элемент в выборку, создавая элемент option, а затем добавляя его в

Я пытался создать весь выбранный элемент в виде строки на сервере и добавить его в форму, но по какой-то причине он не работал в Firefox (что-то пропустил?)

Спасибо

Ответы [ 10 ]

19 голосов
/ 31 марта 2009

500 элементов это не много, даже для IE. Вы должны делать что-то еще, чтобы вызвать отставание.

Я только что попробовал с 500+ опциями в IE6, IE7, FF2 и FF3, и все было почти мгновенно. Я использовал этот код:

var data = [
    { text: 'foo', value: 'bar' },
    // ...
    { text: 'foo', value: 'bar' }
];

var select = document.getElementsByTagName('select')[0];
select.options.length = 0; // clear out existing items
for(var i=0; i < data.length; i++) {
    var d = data[i];
    select.options.add(new Option(d.text, i))
}

Я бы предложил профилировать бит кода, который извлекает данные и заполняет раскрывающийся список. Что-то еще может занимать время. Например, убедитесь, что код, который «разбивает» строковое значение, возвращаемое с сервера, является точным (звучит так, будто вы выполняете там свой собственный анализ).

4 голосов
/ 05 сентября 2012

Первый код в порядке, но у меня лучше работает:

var data = [
    { text: 'uno', value: '1' },
    {text: 'dos', value: '2' }
];

var select = document.getElementById('select-choice-1');
select.options.length = 0; // clear out existing items
for (var i = 0; i < data.length; i++) {
    var d = data[i];
    select.options.add(new Option(d.text, d.value))
}
2 голосов
/ 20 ноября 2009

Проблема всех этих ответов с SelectElement.innerHTML заключается в том, что вы не можете сделать этот трюк с SELECT. Решение состоит в том, чтобы использовать innerHTML для PARENT самого элемента SELECT. Поэтому в вашем коде ajax / jquery / любой другой создайте строку, содержащую ВСЕ HTML-кода SELECT, а затем получите держатель (div или span или любой другой) и установите в innerHTML строку, которую вы создали.

Вам потребуется изолировать SELECT от страницы и дать ему явный родительский элемент (span или div), чтобы другие элементы HTML не становились жертвами при уничтожении / реконструкции элемента SELECT.

Краткий ответ:

parentselectelement.removeChild(selectelement);
parentselectelement.innerHTML = "<select ...><options...></select>";
2 голосов
/ 31 марта 2009

Установка с помощью SelectElement.innerHTML будет самым быстрым ... но , который НЕУДАЧЕТ в IE .

В последний раз, когда я проверял, вы можете сделать это в IE, если обернуть все опции в фиктивный тег или задать полный .outerHTML списка выбора в IE.

1 голос
/ 24 февраля 2012

Не забудьте сначала добавить к document.createDocumentFragment(), прежде чем добавлять его в SELECT.

1 голос
/ 31 марта 2009

Я бы создал все , выделил на сервере и вставил бы его на страницу. Такой подход позволяет обойти досадные расхождения в браузерах и снижает сложность клиентского кода.

Вы упоминали, что пытались это сделать, но в Firefox это не удалось. Я бы предложил настойчиво заставить его работать, опубликовать еще один вопрос с просьбой о помощи по этому вопросу или отредактировать ваш вопрос, чтобы показать нам, что вы сделали, что не работает в Firefox.

0 голосов
/ 12 марта 2013

Если вы не возражаете против использования CoffeeScript, следующий код заполняет список выбора данными JSON в несколько строк.

HTML

<select id="clients"></select>

CoffeeScript

fillList=($list, url)=>
    $.getJSON(url)
    .success((data)->
        $list
        .empty()
        .append("<option value=\"#{item.Id}\">#{item.Name}</option>" for item in data)
    )

$ -> 
    fillList($('#clients'), '/clients/all')

Примечание : цикл внутри append генерирует всю строку html перед вызовом append метода один раз . Это красиво и эффективно.

Пример JSON

[
  {"Id":"1","Name":"Client-1"},
  {"Id":"2","Name":"Client-2"}
]
0 голосов
/ 04 января 2013

Мне нравятся ответы Crescent Fresh и Kemal Fadillah, так как оба используют:

select.options.add(new Options(name, value))

Что касается объекта данных, я рекомендую небольшую настройку следующим образом:

var data = {
  'uno': 1,
  'dos': 2
};

var select = document.getElementById('select-choice-1');
select.options.length = 0; // clear out existing items
for (var i in data) {
      select.options.add(new Option(i, data[i]));
}
0 голосов
/ 31 марта 2009

Когда я использую первую версию, она работает, но может очень медленно обновлять второй выбор

<html>
<form id='myform' method='post' action='$_SERVER[PHP_SELF]'>
<table>
<tr><td><select onselect='CALL_AJAX_AND_UPDATE();'></select></td></tr>
<tr><td><select id='selectid'></select></td></tr>
</table>
</form>
</html>

<script type=\"text/javascript\">
function UPDATE( updatedata )
{                   
    var itemid = document.getElementById('selectid');               

    var data = updatedata.split( '|' );
    var len = data.length;                                                          

    for( i=0; i < len; i ++ )
    {
        var opt = document.createElement('option');
        opt.text = data[i];

        try
        {
            itemid.add( opt, null );                        
        }
        catch(ex)
        {
            itemid.add( opt );      
        }       
    }                                           
}
</script>

Эта версия работает в IE, но Firefox, похоже, не публикует данные второго выбора. Я что-то пропустил с этим.

<html>
<form id='myform' method='post' action='$_SERVER[PHP_SELF]'>
<table>
<tr><td><select onselect='CALL_AJAX_AND_UPDATE();'></select></td></tr>
<tr><td><div id='addselect'></div></td></tr>
</table>
</form>
</html>

<script type=\"text/javascript\">
function UPDATE( updatedata )
{               
    // update data is full select html  
    var itemid = document.getElementById('addselect');              
    itemid.innerHTML = updatedata;                                                          
}
</script>
0 голосов
/ 31 марта 2009

Очень помогло бы увидеть ваш код.

Если вы создаете <option> элемент и , добавляя его на каждой итерации, вам следует рассмотреть возможность создания всех элементов <option> сразу, а затем добавить их все сразу.

Итак (в псевдокоде):

// Don't do this:
for choice in choices:
    option = new Options(choice)
    select.append(option)


// Do this instead
var options = array()

for choice in choices:
   options.append( new Options(choice) )

for option in options:
   select.append(option)

// Or you might try building the select element off-screen and then appending to the DOM
var options = array()
var select = new SelectElement()

for choice in choices:
   select.append( new Options(choice) )

dom_element.append(select)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...