AngularJS页面访问时出现页面闪烁问题的解决


Posted in Javascript onMarch 06, 2016

我们知道在应用的页面或者组件需要加载数据时,浏览器和angular渲染页面都需要消耗一定的时间。这里的间隔可能很小,甚至让人感觉不到区别;但也可能很长,这样会导致让我们的用户看到了没有被渲染过的页面。

这种情况被叫做Flash Of Unrendered Content (FOUC)(K)?and is always unwanted.下面我们将要介绍几个不同的方式防止这种情况发生在我们的用户身上。

1、ng-cloak
ng-cloak指令是angular的内置指令,它的作用是隐藏所有被它包含的元素:

<div ng-cloak>
 <h1>Hello {{ name }}</h1>
</div>

Ng-cloak实现原理为一个directive,页面初始化是在DOM的heade增加一行CSS代码,如下:

<pre class= “prettyprint linenums”>

  [ng\:cloak],[ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak{

  Display:none ! important;

}

</pre>

<pre class= “prettyprint linenums”>
 
  [ng\:cloak],[ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak{
 
  Display:none ! important;
 
}
 
</pre>

Angular将带有ng-cloak的元素设置为display:none.

在等到angular解析到带有ng-cloak节点的时候,会把元素上ng-cloak  attribute和calss同时remove掉,这样就防止了节点的闪烁。如下:

<script type =”text/ng-template” id =”scenario.js-150”>

  It(‘should remove the template directive and css class',function(){

 Expect(element(‘.doc-example-live #template1').attr(‘ng-cloak'))

  not().toBeDefined();

   Expect(element(‘.doc-example-live #template2').attr(‘ng-cloak')).

Not().toBeDefined();

});

</script>

<script type =”text/ng-template” id =”scenario.js-150”>
 
  It(‘should remove the template directive and css class',function(){
 
 Expect(element(‘.doc-example-live #template1').attr(‘ng-cloak'))
 
  not().toBeDefined();
 
   Expect(element(‘.doc-example-live #template2').attr(‘ng-cloak')).
 
Not().toBeDefined();
 
});
 
</script>

2、ng-bind
ng-bind是angular里面另一个内置的用于操作绑定页面数据的指令。我们可以使用ng-bind代替{{ }}的形式绑定元素到页面上;

使用ng-bind替代{{  }}可以防止未被渲染的{{ }}就展示给用户了,使用ng-bind渲染的空元素替代{{ }}会显得友好很多。

上面的例子可以重写成下面那样,这样就可以防止页面出现{{ }}了

<div>
 <h1>Hello <span ng-bind="name"></span></h1>
</div>

3、resolve
当在不同的页面之间使用routes(路由)的时候,我们有另外的方式防止页面在数据被完全加载到route之前被渲染。

在route(路由)里使用resolve可以让我们在route(路由)被完全加载之前获取我们需要加载的数据。当数据被加载成功之后,路由就会改变而页面也会呈现给用户;数据没有被加载成功route就不会改变, the $routeChangeError event will get fired.【$routeChangeError事件就(不)会被激活?】

angular.module('myApp', ['ngRoute'])
.config(function($routeProvider) {
 $routeProvider
 .when('/account', {
 controller: 'AccountCtrl',
 templateUrl: 'views/account.html',
 resolve: {
  // We specify a promise to be resolved
  account: function($q) {
  var d = $q.defer();
  $timeout(function() {
   d.resolve({
   id: 1,
   name: 'Ari Lerner'
   })
  }, 1000);
  return d.promise;
  }
 }
 })
});

resolve 项需要一个key/value对象,key是resolve依赖的名称,value可以是一个字符串(as a service)或者一个返回依赖的方法。

resolve is very useful when the resolve value returns a promise that becomes resolved or rejected.

当路由加载的时候,resolve参数里的keys可以作为可注入的依赖:

angular.module('myApp')
.controller('AccountCtrl', 
 function($scope, account) {
 $scope.account = account;
});

我们同样可以使用resolve key传递$http方法返回的结果,as $http returns promises from it's method calls:

angular.module('myApp', ['ngRoute'])
.config(function($routeProvider) {
 $routeProvider
 .when('/account', {
 controller: 'AccountCtrl',
 templateUrl: 'views/account.html',
 resolve: {
  account: function($http) {
  return $http.get('http://example.com/account.json')
  }
 }
 })
});

推荐定义一个独立的service的方式来使用resolve key,并且使用service来相应返回所需的数据(这种方式更容易测试)。要这样处理的话,我们需要创建一个service:

首先,看一下accountService,

angular.module('app')
.factory('accountService', function($http, $q) {
 return {
 getAccount: function() {
  var d = $q.defer();
  $http.get('/account')
  .then(function(response) {
  d.resolve(response.data)
  }, function err(reason) {
  d.reject(reason);
  });
  return d.promise;
 }
 }
})

定义好service之后我们就可以使用这个service来替换上面代码中直接调用$http的方式了:

angular.module('myApp', ['ngRoute'])
.config(function($routeProvider) {
 $routeProvider
 .when('/account', {
 controller: 'AccountCtrl',
 templateUrl: 'views/account.html',
 resolve: {
  // We specify a promise to be resolved
  account: function(accountService) {
  return accountService.getAccount()
  }
 }
 })
});
Javascript 相关文章推荐
JavaScript初学者应注意的七个细节小结
Jan 30 Javascript
jquery实现在页面加载的时自动为日期插件添加当前日期
Aug 20 Javascript
谈谈JavaScript异步函数发展历程
Sep 29 Javascript
jquery+json实现动态商品内容展示的方法
Jan 14 Javascript
Angular2内置指令NgFor和NgIf详解
Aug 03 Javascript
HTML5 实现的一个俄罗斯方块实例代码
Sep 19 Javascript
Bootstrap3 Grid system原理及应用详解
Sep 30 Javascript
vue 2.0路由之路由嵌套示例详解
May 08 Javascript
VueJs组件prop验证简单介绍
Sep 12 Javascript
详解vue.js数据传递以及数据分发slot
Jan 20 Javascript
React key值的作用和使用详解
Aug 23 Javascript
JS实现根据详细地址获取经纬度功能示例
Apr 16 Javascript
JavaScript模拟数组合并concat
Mar 06 #Javascript
JavaScript模拟push
Mar 06 #Javascript
JavaScript中利用jQuery绑定事件的几种方式小结
Mar 06 #Javascript
Node.js模块封装及使用方法
Mar 06 #Javascript
JavaScript中三种异步上传文件方式
Mar 06 #Javascript
JavaScript中获取纯正的undefined的方法
Mar 06 #Javascript
JS面向对象编程详解
Mar 06 #Javascript
You might like
PHP 单引号与双引号的区别
2009/11/24 PHP
php 缩略图实现函数代码
2011/06/23 PHP
php+xml实现在线英文词典之添加词条的方法
2015/01/23 PHP
总结PHP中DateTime的常用方法
2016/08/11 PHP
php实现留言板功能(代码详解)
2017/03/28 PHP
js操纵dom生成下拉列表框的方法
2014/02/24 Javascript
js实现图片和链接文字同步切换特效的方法
2015/02/20 Javascript
JQuery中绑定事件(bind())和移除事件(unbind())
2015/02/27 Javascript
javascript三元运算符用法实例
2015/04/16 Javascript
被遗忘的javascript的slice() 方法
2015/04/20 Javascript
纯javascript模仿微信打飞机小游戏
2015/08/20 Javascript
JavaScript希尔排序、快速排序、归并排序算法
2016/05/08 Javascript
javascript history对象详解
2017/02/09 Javascript
微信小程序promsie.all和promise顺序执行
2017/10/27 Javascript
详细分析JS函数去抖和节流
2017/12/05 Javascript
详解Python的Django框架中的templates设置
2015/05/11 Python
python字符串对其居中显示的方法
2015/07/11 Python
python 矩阵增加一行或一列的实例
2018/04/04 Python
python pands实现execl转csv 并修改csv指定列的方法
2018/12/12 Python
python数据分析:关键字提取方式
2020/02/24 Python
python如何爬取网页中的文字
2020/07/28 Python
python从PDF中提取数据的示例
2020/10/30 Python
Coggles美国/加拿大:高级国际时装零售商
2018/10/23 全球购物
保加利亚手表、香水、化妆品和珠宝购物网站:Brasty.bg
2020/04/22 全球购物
金融专业个人求职信
2013/09/22 职场文书
《中华少年》教学反思
2014/02/15 职场文书
2014坚持党风廉政建设思想汇报
2014/09/18 职场文书
作弊检讨书
2015/01/27 职场文书
三峡大坝导游词
2015/01/31 职场文书
教师调动申请报告
2015/05/18 职场文书
经济纠纷起诉状
2015/05/20 职场文书
初中毕业感言300字
2015/07/31 职场文书
护理培训心得体会
2016/01/22 职场文书
《勇者辞职不干了》上卷BD发售宣传CM公开
2022/04/08 日漫
解决MySQL报“too many connections“错误
2022/04/19 MySQL
html解决浏览器记住密码输入框的问题
2023/05/07 HTML / CSS