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

Какие еще варианты замены всего HTML-документа через W3C DOM?

Мне любопытно, как люди сталкиваются с заменой всего документа во время выполнения в веб-приложении Ajax. Это редко, но я нашел несколько ситуаций, когда для приложения требуется полная перестройка страницы, и все присутствует локально, не нуждаясь в другом сервере в оба конца.

Я могу легко подготовить новый документ как новое дерево DOM или как String. Поэтому я оцениваю компромиссы для различных подходов.

Если я хочу использовать метод String, это работает:

document.open();
document.write(newStringDoc);
document.close();

Большинство браузеров делают это очень хорошо, но многие из них слегка мерцают при повторном рендеринге. Я заметил, что во второй раз через Firefox 4.0b7 будет просто сидеть и вращаться, как будто он загружается. Нажатие кнопки остановки на панели местоположения, похоже, завершает визуализацию страницы. ( Изменить:, это исправлено в 4.0b8). Этот метод, по-видимому, не позволяет пользователю удалять обновление, чтобы перезагрузить текущий URL (он перезагружает динамически сгенерированную страницу).

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

document.replaceChild(newDomDoc, document.documentElement);

Большинство браузеров, похоже, отлично справляются с этим без мерцания. К сожалению, IE9 beta выбрасывает "DOM Exception: HIERARCHY_REQUEST_ERR (3)" на replaceChild и никогда не завершается. Я не пробовал последнюю версию предварительного просмотра, чтобы убедиться, что это только новая ошибка, которая исправлена. ( Изменить: это исправлено в RC1.)

Мой вопрос: Есть ли у кого-то другой подход, чем любой из этих? У кого-нибудь есть какие-либо другие оговорки, где, возможно, конкретный браузер принципиально ломается с одним из этих подходов?

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

Я считаю, что Gmail использует iframe, встроенные в корневой документ. Похоже, что начальный документ, по крайней мере, для некоторых из этих iframe - это просто пустой документ HTML5, который затем обрабатывает родительский документ.

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

4b9b3361

Ответ 1

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

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

Я также нашел довольно последовательно, что это...

document.replaceChild(newDomDoc, document.documentElement);

... на 2-10x быстрее, чем это...

var doc = document.open("text/html");
doc.write(newStringDoc);
doc.close();

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

Обратите внимание на тонкое изменение хранения возвращаемого document, который обходит ошибку в Firefox 4.0b7.

Также обратите внимание, что этот добавленный тип MIME, который заявляет IE docs, "требуется".

Наконец, Internet Explorer, похоже, немного справляется с устранением тегов ссылок, которые были созданы до того, как новый документ будет заменен. Назначение ссылки href back to itself появляется, чтобы исправить ее.

// IE requires link repair
if (document.createStyleSheet) {
    var head = document.documentElement.firstChild;
    while (head && (head.tagName||"") !== "HEAD") {
        head = head.nextSibling;
    }

    if (head) {
        var link = head.firstChild;
        while (link) {
            if ((link.tagName||"") === "LINK") {
                link.href = link.href;
            }
            link = link.nextSibling;
        }
    }
}

Можно было бы покрыть все базы и объединить их вот так...

var doc = document;
try {
    var newRoot = newDoc.toDOM();
    doc.replaceChild(newRoot, doc.documentElement);

    // IE requires link repair
    if (doc.createStyleSheet) {
        var head = newRoot.firstChild;
        while (head && (head.tagName||"") !== "HEAD") {
            head = head.nextSibling;
        }

        if (head) {
            var link = head.firstChild;
            while (link) {
                if ((link.tagName||"") === "LINK") {
                    link.href = link.href;
                }
                link = link.nextSibling;
            }
        }
    }
} catch (ex) {
    doc = doc.open("text/html");
    doc.write(newDoc.toString());
    doc.close();
}

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