Могу ли я использовать JavaScript, чтобы заставить браузер «сбрасывать» любые ожидающие изменения макета? - PullRequest
5 голосов
/ 05 августа 2011

У меня есть библиотека, которая создает пользовательский интерфейс с использованием Javascript, и из-за задействованного динамического содержимого я иногда хочу выложить содержимое в браузер, изучить, как макет был изменен для поддержки этого, а затем выполнить другую логику в зависимости от результата. , Например: определите, не переполнен ли какой-либо текст, и обрежьте его многоточием.

Обычно я реализую это, внося изменения, а затем использую window.setTimeout (0), чтобы дождаться обновления макета и вызвать остальную часть логики. Это, очевидно, неоптимально, так как разные браузеры могут реализовывать минимальное время ожидания, которое слишком медленно, чтобы предотвратить мерцание, или быстрее, которое использует много ЦП.

В идеале я хотел бы внести изменения в DOM, а затем принудительно обновить макет и сразу запустить встроенную логику исправления. Есть идеи?

Ответы [ 4 ]

6 голосов
/ 05 августа 2011

Насколько я понимаю, чтение любого из свойств CSS приведет к перекомпоновке. Вам вообще не нужно setTimeout.

Выдержка из Рендеринг: перекраска, перекомпоновка / ретрансляция, рестайлинг :

Но иногда скрипт может помешать браузеру оптимизировать перекомпоновки и заставить его очистить очередь и выполнить все пакетные изменения. Это происходит, когда вы запрашиваете информацию о стиле, например

 offsetTop, offsetLeft, offsetWidth, offsetHeight
 scrollTop/Left/Width/Height
 clientTop/Left/Width/Height
 getComputedStyle(), or currentStyle in IE

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

Вот список вызовов / свойств API, которые будут инициировать перекомпоновку .

3 голосов
/ 13 октября 2011

Мы столкнулись с сумасшедшей проблемой с IE8 (Firefox, Chrome в порядке). Мы используем toggleClass ('enoMyAddressesHide') для дочернего элемента.

.enoMyAddressesHide{display:none}

Но родительский контейнер (ы) div не обновляет / не изменяет макет своей высоты.

setTimeout (), позиция чтения, ширина чтения и высота элемента не помогают. Наконец мы можем найти рабочее решение:

jQuery(document).ready(function ($) {
    var RefreshIE8Layout = function () {
        $('.enoAddressBook:first').css('height', 'auto');
        var height = $('.enoAddressBook:first').height();
        $('.enoAddressBook:first').css('height', height);
    };

    $(".enoRowAddressInfo .enoRowAddressInfoArea ul li img.enoMyAddresses").click(function () {
        $(this).parent().find(".enoAllInfoInAddressBox,img.enoMyAddresses").toggleClass('enoMyAddressesHide');

        RefreshIE8Layout(); // fix IE8 bug, not refresh the DOM dimension after using jQuery to manipulate DOM
    });
});

Это выглядит глупо, но работает!

0 голосов
/ 04 ноября 2014

Да, вы можете !!

Большинство браузеров оптимизируют процесс перекомпоновки, помещая в очередь изменения и выполняя их партиями. Для сброса изменений в дереве рендеринга требуется получить некоторую информацию о макете (вычисления смещения, getComputedStyle () и значения прокрутки).

var el = document.getElementById("my-element");
var top = el.offsetTop;

Приведенный выше код заставит браузер выполнить изменения в очереди рендеринга, чтобы вернуть правильные значения.

Simple !!

0 голосов
/ 05 августа 2011

Я понятия не имею, что это на самом деле будет работать для вашей реализации, но:

var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = "".concat(myDiv.innerHTML);

Я считаю, что установка innerHTML вызывает перезагрузку DOM для дочернего элемента. Я понятия не имею, что произойдет, если вы охватите это для всего сайта. Похоже, что вы довольно хорошо подключены к DOM повсюду, и этот метод может заставить любые ссылки на узлы, которые вы уже сделали, стать неопределенными. Другими словами:

var mySelect = document.getElementById("mySelect");// suppose this lives in myDiv.
var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = "".concat(myDiv.innerHTML);

В приведенном выше примере я считаю, что вы потеряете ссылку на mySelect. Если у вас есть много чего происходит, и вы используете поля, а не получатели (то есть, не получая каждый элемент, который вам небезразличен, используя $ () или $ get или document.getElementById (..) каждый раз, когда вы получаете к нему доступ), тогда есть большая вероятность того, что этот тип промывки может вас затянуть.

Вы также наверняка потеряете любые данные о состоянии страницы, которые вы не отслеживаете / не настраиваете вручную - текстовые поля с новым текстом от пользователя, флажки, вновь проверенные пользователем и т. Д., Будут повторно инициализированы в их состояние по умолчанию, используя этот подход к промывка.

Удачи - счастливого кодирования!

B

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