Angularjs - элементы ng-cloak / ng-show мигают

222

У меня проблема в angular.js с директивой/классом ng-cloak или ng-show.

Chrome работает отлично, но Firefox вызывает мигание элементов с помощью ng-cloak или ng-show. IMHO вызвано преобразованием ng-cloak/ng-show в style="display: none;", возможно, компилятор Firefox javascript немного медленнее, поэтому элементы появляются некоторое время, а затем скрываются?

Пример:

<ul ng-show="foo != null" ng-cloak>..</ul>
  • 1
    если вы изначально установили display: none style для этих элементов, это решит проблему?
  • 3
    Я попробую это, я пробовал что-то похожее с добавлением класса (который скрывает элемент) и последующим удалением его через js вручную, но это выглядело еще хуже.
Теги:
class

27 ответов

365
Лучший ответ

Хотя документация не упоминает об этом, может быть недостаточно добавить правило 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, поэтому вы увидите мерцание перед компиляцией шаблона.

  • 3
    Также обратите внимание, что такая же проблема может возникнуть, если вы загружаете angular.js с использованием асинхронного загрузчика, такого как require.js, потому что правило css в .js не будет проанализировано во времени. Решение выше исправляет этот сценарий также.
  • 82
    Не решает проблему для меня. Не знаю - я думаю, что браузеры слишком хотят показать вещи на начальном этапе ...
Показать ещё 9 комментариев
44

Как упомянутый в документации, вы должны добавить правило к своему CSS, чтобы скрыть его на основе атрибута ng-cloak:

[ng\:cloak], [ng-cloak], .ng-cloak {
    display: none;
}

Мы используем подобные трюки на сайте "Built with Angular", который вы можете просмотреть в Github: https://github.com/angular/builtwith.angularjs.org

Надеюсь, что это поможет!

  • 4
    angular.js добавляет это правило стиля к заголовку документа. Вам действительно не нужно добавлять это в свой CSS. Тем не менее, это похоже на работу. Я предполагаю, что angular.js не добавляет блок стиля к голове, пока не загрузится angular.
  • 12
    Что действительно упоминается в документации, так это: «Для достижения наилучшего результата скрипт angular.js должен быть загружен в раздел head файла html; в качестве альтернативы правило css (см. Выше) должно быть включено во внешнюю таблицу стилей приложения. "
Показать ещё 5 комментариев
30

Удостоверьтесь, что параметр "Угловое" включен в head HTML. См. ngCloak doc:

Для достижения наилучшего результата angular.js script должен быть загружен в голову раздел html файла; в качестве альтернативы, правило css (выше) должно быть включены во внешнюю таблицу стилей приложения.

  • 3
    да! Я не могу понять, почему люди везде рекомендуют загружать angular.js в конце страницы. Я чувствую себя лучше, если Angular берет на себя управление с самого начала. Мой ng-cloak работает сейчас.
  • 2
    Я согласен - вещь о скриптах, загружаемых в конце, происходит от обычной веб-разработки, где вы хотите, чтобы страница отображала что-то до того, как js сделает свое дело, но в случае angular вы действительно хотите обратное.
Показать ещё 1 комментарий
25

Мне никогда не удавалось использовать ngCloak. Я все еще мерцаю, несмотря на все, что упоминалось выше. Единственный верный способ избежать щелчка - разместить свой контент в шаблоне и включить шаблон. В SPA единственный HTML-код, который будет оцениваться до компиляции с помощью Angular, является вашей главной страницей index.html.

Просто возьмите все внутри тела и вставьте его в отдельный файл, а затем:

<ng-include src="'views/indexMain.html'"></ng-include>

Вы никогда не должны мерцать таким образом, поскольку Angular скомпилирует шаблон перед добавлением его в DOM.

  • 1
    Именно то, что я использую - чисто и просто, без болезненных взломов.
  • 2
    Помните, что ng-include создает дополнительный AJAX-запрос для извлечения контента с сервера. Я понял, как трудно, например, никогда не использовать ng-include внутри ng-repeat .
Показать ещё 6 комментариев
19

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>
  • 1
    Хороший, простой ответ. ng-bind - это хороший способ избежать «фигурной скобки» или необходимости использовать ng-cloak на уровне тегов, хотя некоторые считают, что это делает код менее читабельным. Для них я не вижу причины не смешивать два подхода.
  • 1
    ng-bind - это гораздо лучший подход к проблеме, так как другие ответы требуют, чтобы вы загрузили первый угол, и ни при каких обстоятельствах фигурные скобки не мигают
18

В дополнение к принятому ответу, если вы используете альтернативный метод запуска ng-cloak...

Вы также можете добавить некоторые дополнительные особенности в свой CSS/LESS:

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide {
    display: none !important;
}
  • 1
    Это сработало для моего варианта использования, когда ни один из вышеперечисленных, казалось, не справился с работой.
14

У меня была аналогичная проблема, и выяснилось, что если у вас есть класс, содержащий переходы, элемент будет мигать. Я попытался добавить ng-плащ без успеха, но, удалив переход, кнопка перестала мигать.

Я использую ионную структуру, и кнопка-схема имеет этот переход

.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

  • 1
    Но не отключит ли это анимацию для директив ng-hide / show?
  • 1
    Я не могу вспомнить Вы попробовали это, и это отключило анимацию?
Показать ещё 1 комментарий
7

У меня возникла проблема, когда <div ng-show="expression"> был первоначально видимым на долю секунды, даже если "выражение" было изначально ложным, прежде чем директива ng-show получила возможность запускать.

Решением, которое я использовал, было вручную добавить класс "ng-hide", как в <div ng-show="expression" ng-hide>, чтобы убедиться, что он начал изначально скрываться. Директива ng-show добавит/удалит класс ng-hide по мере необходимости после этого.

  • 1
    вау, из всех мерзких вариантов, которые я пробовал, это помогло. Спасибо!
  • 0
    Лучшее решение! Это сводило меня с ума в течение нескольких месяцев! Спасибо!
Показать ещё 1 комментарий
6

Попробуйте отключить Firebug. Я серьезно. Это помогает в моем случае.

Примените принятый ответ, а затем убедитесь, что Firebug в Firefox отключен выключен: нажмите F12, затем отключите Firebug для этой страницы - маленькую кнопку в правом верхнем углу.

  • 0
    Да, это сделало это для меня Спасибо!
  • 0
    Спасибо, это сводило меня с ума. Странная ошибка
3

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

Проблема 1: ng-cloak применяется слишком поздно

Эта проблема решается, поскольку во многих ответах на этой странице описано, что AngularJS загружается в голову. См. ngCloak doc:

Для достижения наилучшего результата angular.js script должен быть загружен в голову раздел html файла; в качестве альтернативы, правило css (выше) должно быть включены во внешнюю таблицу стилей приложения.

Проблема 2: ng-cloak слишком быстро удаляется

Эта проблема, скорее всего, возникнет, когда у вас много 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>

(Чтобы избежать проблемы 1, необходимо сохранить ng-cloak.

Затем в вашем приложении app.run установите isPageFullyLoaded:

app.run(['$rootScope', function ($rootScope) {
    $rootScope.$safeApply = function (fn) {
        $rootScope.isPageFullyLoaded = true;
    }
}]);

Помните, что в зависимости от того, что вы делаете, app.run может или не может быть лучшим местом для установки isPageFullyLoaded. Важно убедиться в том, что isPageFullyLoaded получает значение true после того, что вы не хотите мерцания, чтобы оно было открыто пользователю.

Похоже, что Проблема 1 - проблема, с которой сталкивается OP, но другие находят, что это решение не работает или работает только частично, потому что они нажимают Проблема 2 или также.

Важное примечание: Обязательно применяйте решения как к ng-cloak, так и к использованию слишком поздно и удаляться в ближайшее время. Решение только одной из этих проблем не может облегчить симптомы.

  • 1
    это исправило это для меня "скрипт должен быть загружен в главном разделе"
3

Мы столкнулись с этой проблемой в нашей компании и решили ее, добавив "display: none" к стилю CSS для тех мерцающих элементов ng-show. Нам не пришлось вообще использовать ng-cloak. В отличие от других в этом потоке, мы столкнулись с этой проблемой в Safari, но не с Firefox или Chrome - возможно, из-за Safari lazy repaint bug в iOS7.

2

Сохранение приведенных ниже инструкций в главном теге устраняет эту проблему

<style type="text/css">
    [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
    display: none !important;
}
</style>

официальная документация

2

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

С моим запуском с мерцанием я тестировал DevTools open и кеш отключен. Выход из закрытой панели с кешированием позволил устранить мою проблему.

1

Я попробовал решение 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>
1

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

<div <!--...--> style="display: none;" ng-style="style">

Затем в вашем контроллере добавьте это вверху или около нее:

$scope.style = { display: 'block' };

Таким образом, элемент изначально скрыт и отображается только тогда, когда фактически выполняется код контроллера.

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

  • 1
    Это единственное решение, которое сработало для меня
1

вам лучше обратиться к документу angular, потому что версия [1.4.9] имеет обновление ниже, что позволяет поддерживать директиву data-ng-cloak.

[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
  display: none !important;
}
1

Я использую ионную фреймворк, добавив, что CSS-стиль может не работать при определенных обстоятельствах, вы можете попробовать использовать ng-if вместо ng-show/ng-hide

ref: https://books.google.com.my/books?id=-_5_CwAAQBAJ&pg=PA138&lpg=PA138&dq=ng-show+hide+flickering+in+ios&source=bl&ots=m2Turk8DFh&sig=8hNiWx26euGR2k_WeyaVzdixJ8k&hl=en&sa=X&redir_esc=y#v=onepage&q=ng-show%20hide%20flickering%20in%20ios&f=false

1

Лучше использовать ng-if вместо ng-show. ng-if полностью удаляет и воссоздает элемент в DOM и помогает избежать моргания ng-show.

  • 1
    не тот случай для меня, все еще моргает.
  • 0
    но он также уничтожает все работающие плагины в этой части домена ... (например, jquery ui)
0

Я лично решил использовать атрибут ng-class, а не ng-show. У меня был намного больше успеха в этом маршруте, особенно для всплывающих окон, которые по умолчанию не отображаются.

Что раньше было <div class="options-modal" ng-show="showOptions"></div>

теперь: <div class="options-modal" ng-class="{'show': isPrintModalShown}">

с CSS для параметра-модального класса display: none по умолчанию. Класс show содержит display:block CSS.

0

Я использую 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 при каждом нажатии. Это произошло за счет использования двух переменных области для одной и той же цели вместо одной, но пока это, безусловно, лучший вариант.

0

AS из приведенного выше обсуждения

[ng-cloak] {
                display: none;
            }

- идеальный способ решения проблемы.

  • 0
    не работал для меня
0

Я попробовал все ответы выше, и ничего не получилось. Использование ionic для разработки гибридного приложения и пыталось сделать сообщение об ошибке не мерцающим. Я решил решить проблему, добавив в свой элемент класс ng-hide. У моего div уже есть ng-show, чтобы показать элемент при возникновении ошибки. Добавление ng-hide устанавливает, чтобы div не отображался до загрузки angular. Нет ng-плаща или добавить angular в нужную голову.

0

Я действительно нашел предложение от Rick Strahl Web Log исправил мою проблему отлично (поскольку у меня все еще была странная проблема с ng-cloak, мигающим raw {{code}}, особенно при запуске Firebug):

Ядерный вариант: скрытие содержимого вручную

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

Прежде чем я понял, что я могу явно вставить стиль CSS в страницу, я попытался выяснить, почему ng-cloak не выполнял свою работу. После того, как я потерял час, я, наконец, решил просто спрятать и показать контейнер. Идея проста - сначала скрыть контейнер, а затем показать его один раз, когда Angular выполнил начальную обработку и удаление разметки шаблона со страницы.

Вы можете вручную скрыть содержимое и сделать его видимым после того, как Angular получил контроль. Для этого я использовал:

<div id="mainContainer" class="mainContainer boxshadow"
    ng-app="app" style="display:none">

Обратите внимание на элемент display: none, который явно скрывает элемент на странице.

Затем после того, как Angular выполнит инициализацию и эффективно обработает разметку шаблона на странице, вы можете показать содержимое. Для Angular это "готовое событие" - это функция app.run():

app.run( function ($rootScope, $location, cellService) {        
    $("#mainContainer").show();
    …
});

Это эффективно удаляет отображение: нет стиля и содержимого. К моменту запуска app.run() DOM готов к отображению с заполненными данными или по крайней мере пустыми данными - Angular получил контроль.

  • 0
    Я обнаружил, что это единственное решение, которое работает для меня, но я хотел избежать использования JQuery, поэтому нашел альтернативу. Смотрите мой ответ здесь: stackoverflow.com/a/42527700/4214694
0

Я пробовал каждое решение, размещенное здесь и все еще мелькнувшее в Firefox.

Если это кому-то помогает, я решил это, добавив style="display: none;" в основной контент div, а затем с помощью jQuery (я уже использовал его на странице) $('#main-div-id').show(); после того, как все было загружено после получения данных с сервера;

  • 0
    Я обнаружил, что это единственное решение, которое работает для меня, но я хотел избежать использования JQuery, поэтому нашел альтернативу. Смотрите мой ответ здесь: stackoverflow.com/a/42527700/4214694
0

В дополнение к другим ответам, если вы обнаружите, что Flash-код шаблона все еще существует, вероятно, у вас есть ваши сценарии внизу страницы, а это значит, что директива ng-cloak прямо не работает. Вы можете либо переместить свои скрипты в голову, либо создать правило CSS.

В документах сказано: "Для достижения наилучшего результата angular.js script должен быть загружен в разделе заголовка html-документа, в качестве альтернативы, правило css выше должно быть включено во внешнюю таблицу стилей приложения."

Теперь он не должен быть внешней таблицей стилей, а просто элементом в голове.

<style type="text/css">
  .ng-cloak {
    display: none !important;
  }
</style>

источник: https://docs.angularjs.org/api/ng/directive/ngCloak

0

Я бы обернул <ul> с помощью <div ng-cloak>

  • 2
    Ему не нужно оборачивать <ul> . ng-cloak будет скрывать любой элемент, к которому он применяется, а также потомков этого элемента.
-1

Избегайте разрыва строки

<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';">

Ещё вопросы

Сообщество Overcoder
Наверх
Меню