Angularjs - ng-cloak / ng-show元素闪烁

时间:2012-06-28 17:19:12

标签: javascript class angularjs

我在angular.js中遇到指令/类ng-cloakng-show的问题。

Chrome工作正常,但Firefox导致ng-cloakng-show元素闪烁。 恕我直言,这是由ng-cloak / ng-show转换为style="display: none;"引起的,可能是Firefox javascript编译器稍慢一点,所以元素出现一段时间然后隐藏?

示例:

<ul ng-show="foo != null" ng-cloak>..</ul>

29 个答案:

答案 0 :(得分:383)

虽然文档没有提到它,但将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,因此您将在模板编译之前看到闪烁

答案 1 :(得分:46)

作为mentioned in the documentation,您应该在CSS中添加一条规则,以便根据ng-cloak属性隐藏它:

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

我们在“Built with Angular”网站上使用类似的技巧,您可以在Github上查看源代码:https://github.com/angular/builtwith.angularjs.org

希望有所帮助!

答案 2 :(得分:32)

确保AngularJS包含在HTML的head中。见ngCloak doc

  

为获得最佳效果,必须在头部加载angular.js脚本   html文件的一部分;或者,css规则(上面)必须是   包含在应用程序的外部样式表中。

答案 3 :(得分:27)

我使用ngCloak从来没有太多运气。尽管如上所述,我仍然会闪烁。避免轻弹的唯一可靠方法是将您的内容放在模板中并包含模板。在SPA中,唯一将在Angular编译之前评估的HTML是您的主要index.html页面。

只需取出身体内的所有物品并将其粘贴在单独的文件中,然后:

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

你不应该以任何方式闪烁,因为Angular会在将模板添加到DOM之前编译模板。

答案 4 :(得分:22)

ngBindngBindTemplate是不需要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>

答案 5 :(得分:19)

如果你正在使用另一种触发ng-cloak的方法,那么除了接受的答案......

您可能还希望为CSS / LESS添加一些额外的特性:

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

答案 6 :(得分:15)

我有一个类似的问题,并发现如果你有一个包含转换的类,该元素将闪烁。我试图添加ng-cloak但没有成功,但是通过删除转换,按钮停止闪烁。

我使用离子框架,按钮轮廓有这种转变

.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

答案 7 :(得分:9)

我遇到一个问题,<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.william.better_gps" > <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <receiver android:name=".SmsReceiver" android:enabled="true"> <intent-filter android:priority="999"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> </application> </manifest> 最初会在几分之一秒内可见,即使&#34;表达&#34;在ng-show指令有机会运行之前,它最初是假的。

我使用的解决方案是手动添加&#34; ng-hide&#34;类,如curl -XPOST 'localhost:9200/bank/_search?pretty' -d ' { "query": { "prefix" : { "firstname" : "op" } } }' 中所示,以确保它最初隐藏起来。 ng-show指令将在必要时添加/删除ng-hide类。

答案 8 :(得分:7)

尝试关闭Firebug 。我很认真。这有助于我的情况。

应用已接受的答案,然后确保Firefox中的 Firebug 关闭:按F12,然后关闭此页面的Firebug - 右上角的小按钮。

答案 9 :(得分:6)

实际上有两个可能导致闪烁问题的独立问题,您可能面临其中一个或两个问题。

问题1:ng-cloak应用太晚

此问题已解决,因为此页面上的许多答案都是为了确保AngularJS加载到头部。见ngCloak doc

  

为获得最佳效果,必须在头部加载angular.js脚本   html文件的一部分;或者,css规则(上面)必须是   包含在应用程序的外部样式表中。

问题2:过早删除ng-cloak

如果您的网页上有很多CSS,并且规则层叠在一起,并且在应用顶层图层之前CSS的较深层会闪烁,则最有可能发生此问题。

在你的元素中添加style="display:none"的答案中的jQuery解决方案确实可以解决这个问题,只要样式被删除得足够晚(实际上这些解决方案可以解决这两个问题)。但是,如果您不想直接在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 或者也是。

  

重要提示:请务必将解决方案应用于过早应用的ng-cloak并尽快删除。仅解决这些问题中的一个可能无法缓解症状。

答案 10 :(得分:4)

我们在我们公司遇到了这个问题,并通过在CSS样式中添加“display:none”来解决这个问题,因为那些闪烁的ng-show元素。我们根本不必使用ng-cloak。与此线程中的其他人不同,我们在Safari中遇到了此问题,但未在Firefox或Chrome中遇到过此问题 - 可能是由于Safari's lazy repaint bug in iOS7

答案 11 :(得分:3)

对于它的价值,我有一个类似的问题ng-cloak无法正常工作。可能值得检查您的app / site,并启用缓存以重用源文件以查看是否有帮助。

随着我的闪回磨合,我正在测试DevTools打开并禁用缓存。通过缓存启用关闭面板解决了我的问题。

答案 12 :(得分:3)

在head标记中保留以下语句可修复此问题

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

official documentation

答案 13 :(得分:3)

我无法使用这些方法,所以我最终做了以下工作。对于您最初想要隐藏的元素:

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

然后在您的控制器中,将其添加到顶部或附近:

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

这样,元素最初是隐藏的,只显示控制器代码实际运行的时间。

您可以根据需要调整展示位置,也许可以添加一些逻辑。在我的情况下,如果当前没有登录,我会切换到登录路径,并且不希望我的界面事先闪烁,所以我在登录检查后设置$scope.style

答案 14 :(得分:2)

最好使用ng-if代替ng-showng-if完全删除并重新创建DOM中的元素,并有助于避免ng-shows闪烁。

答案 15 :(得分:2)

答案 16 :(得分:2)

你最好参考角文档,因为版本[1.4.9]有更新到下面,使它可以支持data-ng-cloak指令。

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

答案 17 :(得分:2)

我尝试过上面的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>

答案 18 :(得分:1)

尝试ng-cloak但仍然短暂眨眼。下面的代码完全消除了它们。

<body style="display:none;" ng-style="{'display':'block'}">

答案 19 :(得分:1)

上面列出的所有解决方案都不适合我。然后,我决定看一下实际功能,并意识到,当“ $ scope.watch”被触发时,它是在name字段中输入了一个值,但实际情况并非如此。因此,在代码中我设置了oldValue和newValue然后

$scope.$watch('model.value', function(newValue, oldValue) {
if (newValue !== oldValue) {
validateValue(newValue);
}
});

本质上,在这种情况下触发scope.watch时,AngularJS监视名称变量(model.value)的更改

答案 20 :(得分:1)

我在指令中使用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插入操作。这是以两个范围变量用于相同目的而不是一个为代价而牺牲的,但到目前为止这绝对是最好的选择。

答案 21 :(得分:1)

来自上述讨论的AS

[ng-cloak] {
                display: none;
            }

是解决问题的最佳方式。

答案 22 :(得分:1)

我尝试了上面的所有答案,没有任何效果。使用离子来开发混合应用程序,并试图使错误消息不闪烁。 我最后通过在我的元素中添加一个ng-hide类来解决我的问题。我的div已经有ng-show来显示错误时的元素。添加ng-hide会将div设置为在加载角度之前不显示。没有必要的斗篷或增加角度到必要的。

答案 23 :(得分:1)

我实际上发现Rick Strahl's Web Log的建议完全解决了我的问题(因为我仍然有一些奇怪的问题,有时会使用ng-cloak闪烁原始{{code}},尤其是在运行Firebug时):

核选项:手动隐藏内容

使用显式CSS是最佳选择,因此不应该使用以下内容。但我在这里会提到它,因为它提供了一些有用的信息,可以为其他框架或基于标记的模板在加载时手动隐藏/显示内容。

在我发现我可以明确地将CSS样式嵌入页面之前,我曾试图找出为什么ng-cloak没有完成它的工作。浪费了一个小时后,我终于决定只手动隐藏并显示容器。这个想法很简单 - 最初隐藏容器,然后在Angular完成初始处理并从页面中删除模板标记后显示它。

您可以手动隐藏内容,并在Angular获得控制权后使其可见。为此,我使用了:

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

注意display:none样式最初在页面上显式隐藏元素。

然后,一旦Angular运行其初始化并有效处理页面上的模板标记,您就可以显示内容。对于Angular,这个'ready'事件是app.run()函数:

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

这有效地删除了display:none样式并显示内容。当app.run()触发时,DOM已准备好显示填充数据或至少是空数据 - Angular已获得控制权。

答案 24 :(得分:1)

我尝试了在这里发布的所有解决方案,但仍然在Firefox中闪烁。

如果它对任何人有帮助,我通过将style="display: none;"添加到主内容div,然后使用jQuery(我已经在页面上使用它)$('#main-div-id').show();解决了一切,一旦从获取数据后加载了所有内容服务器;

答案 25 :(得分:1)

除了其他答案之外,如果您发现模板代码的闪存仍然存在,则可能是您的脚本位于页面底部,这意味着ng-cloak指令直接启动将不起作用。您可以将脚本移动到头部或创建CSS规则。

文档说“为了获得最佳结果,必须在html文档的head部分加载angular.js脚本;或者,上面的css规则必须包含在应用程序的外部样式表中。”

现在,它不必是外部样式表,而只是在头部的元素中。

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

来源:https://docs.angularjs.org/api/ng/directive/ngCloak

答案 26 :(得分:0)

我个人决定使用ng-class属性而不是ng-show。我在这条路线上取得了更大的成功,特别是对于默认情况下始终未显示的弹出窗口。

过去是<div class="options-modal" ng-show="showOptions"></div>

现在是:<div class="options-modal" ng-class="{'show': isPrintModalShown}">

默认情况下,options-modal类的CSS为display: none。 show类包含display:block CSS。

答案 27 :(得分:0)

我会用<ul>

包裹<div ng-cloak>

答案 28 :(得分:-2)

避免换行

<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';">
相关问题