На мобильном устройстве слишком поздно использовать display none, блок

#javascript #css #performance #responsive-design

#javascript #css #Производительность #адаптивный дизайн

Вопрос:

На ПК это работает хорошо. но для мобильных устройств уже слишком поздно. есть ли какой-либо другой более быстрый метод или другие?

 function country_change(country,countries)
{   
    var cls = document.getElementsByClassName("country_events"); 

    if(document.readyState == "loading")
    { 
        alert('not loading.');
    } else 
    {   
        for (n=0; n < cls.length; n  ) 
        {   

            var elem = cls[n];
            var div_elem = elem.getElementsByTagName('div').length;

            for (m=1; m < div_elem; m  ) 
            {   
                if (elem.getAttribute('name') == country)
                {
                    if (elem.getElementsByTagName('div')[m].style.display == "none")
                    {
                        elem.getElementsByTagName('div')[m].style.display="block";
                        increaseHeight()
                    }
                }
                else
                {
                        elem.getElementsByTagName('div')[m].style.display="none";
                        increaseHeight()
                }
            }
        }
    }    
}   
 

на ПК это работает около 1 ~ 3 секунд, но для мобильных устройств это занимает почти 10 ~ 20 секунд.
я думаю, что display — плохой метод, но другого способа нет, не так ли?

Комментарии:

1. Вы можете значительно оптимизировать цикл, удалив многие вызовы getElementsByClassName .

2. Из-за использования getElementByClassName это всего 20 ~ 30 объектов.

3. Конечно, но вы вызываете его 3 раза вместо одного раза. Это дорогостоящий метод для вызова и работы, поскольку это живой список узлов. Статическое использование cls тоже поможет. Это легкий большой выигрыш в производительности. Нет обещаний, что это будет очень быстро, но, вероятно, заметно быстрее.

Ответ №1:

Коллекция, возвращенная:

 var cls = document.getElementsByClassName("country_events"); 
 

работает, поэтому для любого изменения DOM может потребоваться, чтобы браузер обновил коллекцию. Это может происходить намного чаще, чем вы думаете (и гораздо чаще в некоторых браузерах, чем в других), поэтому вы можете преобразовать это в массив или использовать querySelectorAll (который возвращает статическую коллекцию) вместо этого:

 var cls = document.querySelectorAll(".country_events"); 
 

Тогда у вас есть:

         var elem = cls[n];
        var div_elem = elem.getElementsByTagName('div').length;
 

поэтому хорошо кэшировать elem, но getElementsByTagName также возвращает текущую коллекцию, поэтому снова используйте querySelectorAll:

         var div_elem = elem.querySelectorAll('div').length;
 

div_elem кажется неподходящим именем, возможно, divCount было бы лучше?

Затем:

             if (elem.getAttribute('name') == country)
 

вы можете сохранить вызов метода, обратившись к свойству напрямую:

             if (elem.name == country)
 

И тогда ужасно бесполезно:

        if (elem.getElementsByTagName('div')[m].style.display == "none")
                {
                    elem.getElementsByTagName('div')[m].style.display="block";
                    increaseHeight()
 

Вы получили список divs ранее, поэтому кэшируйте его там

   var divs = elem.querySelectorAll('div');
  var divCount = divs.length;
 

Теперь повторно используйте его:

        if (divs[m].style.display == 'none') {
         divs[m].style.display = '';
       } else {
         divs[m].style.display = 'none';
       }
       increaseHeight();
 

который можно сократить до:

        divs[m].style.display == divs[m].style.display == 'none'? '' : 'none';
       increaseHeight();
 

Однако условный оператор обычно работает медленнее, чем эквивалентный if..else .

Таким образом, функция становится:

 function country_change(country,countries) {   
    var cls = document.querySelectorAll('.country_events'); 

    if(document.readyState == "loading") { 
        alert('not loading.');

    } else {   

        for (var n=0, nLen=cls.length; n<nLen; n  ) {
            var elem = cls[n];
            var divs = elem.querySelectorAll('div');
            var divCount = divs.length;

            for (var m = 1; m < divCount; m  ) {

                if (elem.name == country) {

                    if (divs[m].style.display == 'none') {
                        divs[m].style.display = '';

                    } else {
                      divs[m].style.display = 'none';
                    }

                    increaseHeight()
                }
             }
         }    
    }
} 
 

Обратите внимание, что querySelectorAll не поддерживается IE 7 и ниже.

Установка для element.style.display значения » (пустая строка) позволяет ему вернуться к своему стилю по умолчанию или вычисляемому стилю и означает, что вам не нужно знать, что это такое для каждого отдельного типа элемента или что включено в правила CSS.

Комментарии:

1. я последовал за вами, но (divs = elem. querySelectorAll(‘div’); div_elem[m].style.display), похоже, не может изменить отображение. это что-нибудь случится.