Подтвердить что ты не робот

Почему Chrome использует больше CPU, когда скрыт большой элемент Knockout?

У меня одностраничное веб-приложение, которое использует Knockout.js 2.2.1 для отображения потоковой передачи информации с сервера (используя socket.io, хотя я не думаю, что это важно). Это приложение также содержит большую таблицу данных, которая создается из объекта JSON с использованием привязок Knockout foreach. (Таблица большая, но не огромная: 20 столбцов и 200 строк или около того.)

Поскольку таблица большая, ее можно открыть/закрыть пользователем, нажав кнопки. Данные <table> помещаются внутри элемента <div>, который можно скрыть/показать с помощью методов jQuery .hide() и .show() (которые по существу работают путем установки и очистки CSS display: none на <div>).

Вся эта функциональность работает. Тем не менее, я замечаю, что после "закрытия" (скрытия) таблицы больших данных использование процессора Chrome скачкообразно - на 100%, если таблица с генерируемым нокаутом достаточно велика. Еще интереснее то, что это происходит только после того, как пользователь щелкнул где-то внутри элемента <div>, который содержит таблицу, когда она отображается. Когда таблица скрыта (и загрузка процессора высока), щелчок в другом месте страницы вернет загрузку ЦП в нормальное русло. Процесс будет повторяться по желанию.

Еще одно полезное замечание: если я остановлю потоковые данные с сервера, эта проблема не произойдет (или это не заметно при использовании ЦП). На этой странице есть одна модель представления нокаута, которая управляет потоковыми данными с сервера и созданием этой таблицы данных из объекта JSON. Оба набора данных в остальном полностью разделены - ни одна из изменяющихся данных не отображается в таблице, и таблица не содержит привязки событий к модели представления. Как будто обновление потоковых данных модели Knockout вызывает работу над таблицей данных, даже если ни одна из данных потоковой передачи не привязана к таблице. И это происходит только тогда, когда таблица не отображается!

Краткое резюме:

  • Веб-приложение использует нокаут для визуализации большой таблицы данных при загрузке страницы.
  • Эта таблица скрыта при .hide() при запуске в $(document).ready, но отображается с помощью .show() после нажатия кнопки и может быть снова скрыта
  • Если щелкнуть мышью внутри таблицы данных, использование ЦП в Chrome переместится на 100% после того, как таблица снова будет скрыта.
  • Щелчок по чему-либо еще на странице приведет к нормальному использованию ЦП.

Другая важная информация:

  • Профайлер Chrome JavaScript показывает высокую загрузку процессора, но он классифицируется просто как (программа).
  • Ни IE10, ни Firefox 20 в Windows не показывают эту проблему.

Любые идеи о том, что происходит здесь, или предложения по дополнительным устранению неполадок?

jsFiddle:

Пример здесь: http://jsfiddle.net/CTYMv/6/

Посмотрите на использование ЦП после загрузки скрипта, он должен быть низким. Нажмите "Показать таблицу", а затем щелкните где-нибудь внутри всплывающего div (серый фон). Затем нажмите "Скрыть таблицу" - использование ЦП значительно возрастет. Затем щелкните в другом месте (белый фон), и CPU вернется в нормальное состояние.

4b9b3361

Ответ 1

Я думаю, теперь мы можем утверждать, что это ошибка в движке webkit. Эта ошибка появляется только при использовании свойства css display:none;. Это связано с тем, как графический процессор с использованием webkit визуализирует скрытые элементы? Ну, я до сих пор не знаю...

СМОТРЕТЬ ДЕМО

Это простейшее обходное решение, о котором я могу думать, это не должно мешать никакому другому вашему коду: {например, нокаут наблюдаемый}

CSS: {добавлены указатели-события, предложенные Брэндоном}

.hidden{opacity:0;pointer-events:none} //don't use display:none here

JS:

//don't use hide/show jq methods as internally it set display none (fadeOut() methods too)
$('#btn_show').click(function(){
    $('#bigdatadiv').removeClass('hidden');
});
$('#btn_hide').on('click',function(){    
   $('#bigdatadiv').addClass('hidden')
});

Я знаю, что это всего лишь обходной путь и который все еще не отвечает на ваш вопрос: почему это происходит?

Ответ 2

Спасибо за эту тему; вы могли бы подумать, что ошибка будет исправлена ​​через 2 года.

window.getSelection(). removeAllRanges() разрешил для меня вещи и был самым простым в моем коде.

Ответ 3

Просто используйте window.getSelection().removeAllRanges() перед .hide(); для больших блоков. Работа для меня прекрасна. Это глупо, но это правда.