Angularjs - элементы ng-cloak/ng-show мигают
У меня есть проблема в angular.js с директивой / классом ng-cloak
или же ng-show
,
Chrome работает нормально, но Firefox вызывает мигание элементов с ng-cloak
или же ng-show
, ИМХО это вызвано конвертацией ng-cloak
/ng-show
в style="display: none;"
, вероятно, компилятор JavaScript Firefox немного медленнее, поэтому элементы появляются на некоторое время, а затем скрываются?
Пример:
<ul ng-show="foo != null" ng-cloak>..</ul>
29 ответов
Хотя в документации это не упоминается, этого может быть недостаточно для добавления display: none;
Править к вашему CSS. В случаях, когда вы загружаете angular.js в тело или шаблоны не скомпилированы достаточно быстро, используйте ng-cloak
директива и включите в ваш CSS следующее:
/*
Allow angular.js to be loaded in body, hiding cloaked elements until
templates compile. The !important is important given that there may be
other selectors that are more specific or come later and might alter display.
*/
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none !important;
}
Как уже упоминалось в комментарии, !important
это важно. Например, если у вас есть следующая разметка
<ul class="nav">
<li><a href="/foo" ng-cloak>{{bar}}</a></li>
</ul>
и вы случайно используете bootstrap.css
, следующий селектор более конкретен для вашего ng-cloak
'элемент ed
.nav > li > a {
display: block;
}
Так что, если вы включите правило просто display: none;
, Правило Bootstrap будет иметь приоритет и display
будет установлен в block
, так что вы увидите мерцание до компиляции шаблона.
Как упомянуто в документации, вы должны добавить правило в свой CSS, чтобы скрыть его на основе ng-cloak
атрибут:
[ng\:cloak], [ng-cloak], .ng-cloak {
display: none;
}
Мы используем аналогичные приемы на сайте "Built with Angular", источник которого вы можете увидеть на Github: https://github.com/angular/builtwith.angularjs.org
Надеюсь, это поможет!
Убедитесь, что AngularJS включен в head
HTML. Смотрите документ ngCloak:
Для достижения наилучшего результата скрипт angular.js должен быть загружен в раздел head файла ht ml; альтернативно, правило css (выше) должно быть включено во внешнюю таблицу стилей приложения.
У меня никогда не было большой удачи с использованием ngCloak. Я все еще мерцаю, несмотря на все вышеупомянутое. Единственный надежный способ избежать флик - это поместить ваш контент в шаблон и включить шаблон. В SPA единственным HTML, который будет оценен перед компиляцией Angular, является ваша главная страница index.html.
Просто возьмите все внутри тела и вставьте в отдельный файл, а затем:
<ng-include src="'views/indexMain.html'"></ng-include>
Вы никогда не должны мерцать таким образом, так как Angular скомпилирует шаблон перед добавлением его в DOM.
ngBind и ngBindTemplate являются альтернативами, которые не требуют CSS:
<div ng-show="foo != null" ng-cloak>{{name}}</div> <!-- requires CSS -->
<div ng-show="foo != null" ng-bind="name"></div>
<div ng-show="foo != null" ng-bind-template="name = {{name}}"></div>
В дополнение к принятому ответу, если вы используете альтернативный метод запуска ng-cloak...
Вы также можете добавить некоторые дополнительные особенности к вашему CSS/LESS:
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
display: none !important;
}
У меня была похожая проблема, и я обнаружил, что если у вас есть класс, содержащий переходы, элемент будет мигать. Я безуспешно пытался добавить нг-плащ, но при удалении перехода перестала мигать кнопка.
Я использую ионный каркас и контур кнопки имеет этот переход
.button-outline {
-webkit-transition: opacity .1s;
transition: opacity .1s;
}
Просто перезапишите класс, чтобы удалить переход, и кнопка перестанет мигать.
Обновить
Опять же на ионном появляется мерцание при использовании ng-show / ng-hide. Добавление следующего CSS разрешает это:
.ng-hide-add,
.ng-hide-remove {
display: none !important;
}
Источник: http://forum.ionicframework.com/t/beta-14-ng-hide-show/14270/9
У меня была проблема, когда <div ng-show="expression">
Первоначально будет виден в течение доли секунды, даже если "выражение" изначально было ложным, прежде чем директива ng-show получила возможность запуска.
Решение, которое я использовал, состояло в том, чтобы вручную добавить класс "ng-hide", как в <div ng-show="expression" ng-hide>
, чтобы убедиться, что он изначально скрыт. После этого директива ng-show добавит / удалит класс ng-hide по мере необходимости.
Попробуйте выключить Firebug. Я серьезно. Это помогает в моем случае.
Примените принятый ответ, а затем убедитесь, что Firebug в вашем Firefox выключен: нажмите F12, затем выключите Firebug для этой страницы - маленькую кнопку в правом верхнем углу.
На самом деле есть две отдельные проблемы, которые могут вызвать проблему мерцания, и вы можете столкнуться с одной или обеими из них.
Проблема 1: нг-плащ применяется слишком поздно
Эта проблема решена, как описано во многих ответах на этой странице, чтобы убедиться, что AngularJS загружен в голову. Смотрите документ ngCloak:
Для достижения наилучшего результата скрипт angular.js должен быть загружен в раздел head файла html; альтернативно, правило css (выше) должно быть включено во внешнюю таблицу стилей приложения.
Проблема 2: нг-плащ удаляется слишком рано
Скорее всего, эта проблема возникает, когда на вашей странице много CSS-кода, правила которого каскадно накладываются друг на друга, а более глубокие слои CSS вспыхивают перед применением верхнего слоя.
Решения jQuery в ответах, включающих добавление style="display:none"
решите эту проблему, пока стиль удаляется достаточно поздно (фактически эти решения решают обе проблемы). Однако, если вы предпочитаете не добавлять стили непосредственно в ваш HTML, вы можете достичь тех же результатов, используя ng-show
,
Начиная с примера из вопроса:
<ul ng-show="foo != null" ng-cloak>..</ul>
Добавьте дополнительное правило ng-show к вашему элементу:
<ul ng-show="isPageFullyLoaded && (foo != null)" ng-cloak>..</ul>
(Вам нужно сохранить ng-cloak
чтобы избежать проблемы 1).
Тогда в вашем наборе app.run isPageFullyLoaded
:
app.run(['$rootScope', function ($rootScope) {
$rootScope.$safeApply = function (fn) {
$rootScope.isPageFullyLoaded = true;
}
}]);
Имейте в виду, что в зависимости от того, что именно вы делаете, app.run может или не может быть лучшим местом для установки isPageFullyLoaded
, Важно убедиться, что isPageFullyLoaded
получает значение true после того, как что-либо, что вы не хотите мигать, готово быть раскрытым пользователю.
Похоже, что проблема 1 - это проблема, с которой сталкивается OP, но другие находят, что решение не работает или работает только частично, потому что вместо этого они сталкиваются с проблемой 2.
Важное примечание: Обязательно наносите растворы на оба нг-плаща, которые наносятся слишком поздно и удаляются в ближайшее время. Решение только одной из этих проблем может не облегчить симптомы.
Мы столкнулись с этой проблемой в нашей компании и решили ее, добавив "display: none" в стиль CSS для тех мерцающих элементов ng-show. Нам не пришлось использовать нг-плащ вообще. В отличие от других в этой теме, мы сталкивались с этой проблемой в Safari, но не с Firefox или Chrome - возможно, из-за ленивой ошибки перерисовки в iOS7 в Safari.
Для чего это стоит, у меня была похожая проблема нг-плащ не работает. Возможно, стоит проверить ваше приложение / сайт с включенным кэшем, чтобы повторно использовать исходные файлы, чтобы выяснить, помогает ли это.
При запуске с мерцанием я тестировал с открытым DevTools и отключенным кешем. Закрытие панели с включенным кэшированием исправило мою проблему.
Keeping the below statements in head tag fixed this issue
<style type="text/css">
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
</style>
Я не смог заставить работать ни один из этих методов, поэтому в итоге я сделал следующее. Для элемента, который вы хотите изначально скрыть:
<div <!--...--> style="display: none;" ng-style="style">
Затем в вашем контроллере добавьте это вверху или около него:
$scope.style = { display: 'block' };
Таким образом, элемент изначально скрыт и отображается только тогда, когда код контроллера действительно запущен.
Вы можете настроить размещение под свои нужды, возможно, добавив немного логики. В моем случае я переключаюсь на путь входа в систему, если в данный момент не вошел в систему, и не хотел, чтобы мой интерфейс мерцал заранее, поэтому я установил $scope.style
после проверки входа в систему.
Вам лучше ссылаться на угловой документ, потому что версия [1.4.9] имеет обновление ниже, чтобы оно могло поддерживать директиву data-ng-cloak.
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
Я попробовал решение ng-cloak выше, но оно по-прежнему имеет проблемы с Firefox. Единственный обходной путь, который мне помог, - задержать загрузку формы до полной загрузки Angular.
Я просто добавил ng-init в приложение и использую ng-if на стороне формы, чтобы проверить, загружена ли заданная мной переменная.
<div ng-app="myApp" ng-init="loaded='yes'">
<form ng-if="loaded.length > 0">
<!--all my elements here-->
</form>
</div>
Я использую ионные рамки, добавление стиля CSS может не работать в определенных обстоятельствах, вы можете попробовать использовать ng-if вместо ng-show / ng-hide
Лучше использовать ng-if
вместо ng-show
, ng-if
полностью удаляет и воссоздает элемент в DOM и помогает избежать мигания ng-шоу.
Пытался ng-cloak
но все же недолго моргает. Ниже код избавит их полностью.
<body style="display:none;" ng-style="{'display':'block'}">
Я попробовал каждое решение, опубликованное здесь, и все еще мерцало в Firefox.
Если это кому-нибудь поможет, я решил это, добавив style="display: none;"
к основному контенту div, затем используя jQuery (я уже использовал его на странице) $('#main-div-id').show();
однажды все было загружено после получения данных с сервера;
В дополнение к другим ответам, если вы обнаружите, что вспышка кода шаблона все еще происходит, вероятно, ваши скрипты находятся внизу страницы, а это означает, что директива ng-cloak прямо вверх не будет работать. Вы можете либо переместить свои скрипты в голову, либо создать правило CSS.
В документах сказано: "Для достижения наилучшего результата скрипт angular.js должен быть загружен в раздел head документа html; в качестве альтернативы приведенное выше правило css должно быть включено во внешнюю таблицу стилей приложения".
Теперь это не должна быть внешняя таблица стилей, а просто элемент в голове.
<style type="text/css">
.ng-cloak {
display: none !important;
}
</style>
источник: https://docs.angularjs.org/api/ng/directive/ngCloak
Я на самом деле обнаружил, что предложение из веб-журнала Рика Страла отлично исправило мою проблему (поскольку у меня все еще была странная проблема с нг-плащем, мигавшим raw {{code}} время от времени, особенно во время работы Firebug):
Ядерный вариант: скрытие контента вручную
Использование явного CSS - лучший выбор, поэтому не должно быть необходимости в следующем. Но я упомяну это здесь, так как это дает некоторое представление о том, как вы можете скрыть / показать контент вручную при загрузке для других платформ или в ваших собственных шаблонах на основе разметки.
Прежде чем я понял, что могу явно встроить стиль CSS в страницу, я попытался выяснить, почему ng-cloak не выполняет свою работу. Потратив час на то, чтобы никуда не деваться, я наконец решил просто вручную спрятать и показать контейнер. Идея проста - сначала спрятать контейнер, а затем показать его, как только Angular выполнит первоначальную обработку и удалит разметку шаблона со страницы.
Вы можете вручную скрыть содержимое и сделать его видимым после того, как Angular получит контроль. Для этого я использовал:
<div id="mainContainer" class="mainContainer boxshadow"
ng-app="app" style="display:none">
Обратите внимание на отображение: ни один из стилей, который явно скрывает элемент изначально на странице.
Затем, как только Angular запустит свою инициализацию и эффективно обработает разметку шаблона на странице, вы сможете показать содержимое. Для Angular это событие 'ready' является функцией app.run():
app.run( function ($rootScope, $location, cellService) {
$("#mainContainer").show();
…
});
Это эффективно удаляет отображение: отсутствует стиль и отображается содержимое. К моменту запуска app.run() DOM готов к отображению с заполненными данными или, по крайней мере, с пустыми данными - Angular уже получил контроль.
Ни одно из перечисленных решений не помогло мне. Затем я решил взглянуть на саму функцию и понял, что когда запускается "$ scope.watch", он помещает значение в поле имени, чего не должно быть. Таким образом, в коде, который я установил и oldValue и newValue тогда
$scope.$watch('model.value', function(newValue, oldValue) {
if (newValue !== oldValue) {
validateValue(newValue);
}
});
По сути, когда в этом случае запускается scope.watch, AngularJS отслеживает изменения в переменной name (model.value)
Я перепробовал все ответы выше и ничего не получалось. Использовал ionic для разработки гибридного приложения и пытался заставить сообщение об ошибке не мерцать. Я решил свою проблему, добавив класс ng-hide к своему элементу. У моего div уже есть ng-show, чтобы показать элемент при возникновении ошибки. Добавив ng-hide, установите div, чтобы он не отображался до загрузки angular. Никакой нг-плащ или добавление углов на голову не требуется.
КАК из приведенного выше обсуждения
[ng-cloak] {
display: none;
}
это идеальный способ решить проблему.
Я использую ng-show в директиве, чтобы показать и скрыть всплывающие окна.
<div class="..." ng-show="showPopup">
Ничто из перечисленного не сработало для меня, и использование ng-if вместо ng-show было бы излишним. Это будет означать удаление и добавление всего всплывающего содержимого в DOM при каждом нажатии. Вместо этого я добавил ng-if в тот же элемент, чтобы он не отображался при загрузке документа:
<div class="..." ng-show="showPopup" ng-if="popupReady">
После этого я добавил инициализацию в контроллер, ответственный за эту директиву, с таймаутом:
$timeout(function () {
$scope.popupReady = true;
});
Таким образом, я устранил проблему мерцания и избежал дорогостоящей операции вставки DOM при каждом щелчке. Это произошло за счет использования двух переменных области видимости для одной цели вместо одной, но пока это определенно лучший вариант.
Я лично решил использовать ng-class
атрибут, а не ng-show
, Я добился гораздо большего успеха, пройдя этот путь, особенно для всплывающих окон, которые всегда не показываются по умолчанию.
Что раньше было <div class="options-modal" ng-show="showOptions"></div>
сейчас: <div class="options-modal" ng-class="{'show': isPrintModalShown}">
с CSS для опционально-модального класса display: none
по умолчанию. Класс шоу содержит display:block
CSS.
Избегайте разрыва строки
<meta http-equiv="Content-Security-Policy" content="
default-src 'FOO';
script-src 'FOO';
style-src 'FOO';
font-src 'FOO';">
Работает с Firefox 45.0.1
<meta http-equiv="Content-Security-Policy" content=" default-src 'FOO'; script-src 'FOO'; style-src 'FOO'; font-src 'FOO';">