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中去掉数组中的重复值的实现方法
Aug 03 Javascript
通过JavaScript使Div居中并随网页大小改变而改变
Jun 24 Javascript
js 得到文件后缀(通过正则实现)
Jul 08 Javascript
javascript 上下banner替换具体实现
Nov 14 Javascript
javascript操作excel生成报表示例
May 08 Javascript
JavaScript输出当前时间Unix时间戳的方法
Apr 06 Javascript
jquery实现叠层3D文字特效代码分享
Aug 21 Javascript
SpringMVC+bootstrap table实例详解
Jun 02 Javascript
angular 实现下拉列表组件的示例代码
Mar 09 Javascript
vue路由权限校验功能的实现代码
Jun 07 Javascript
vue基于better-scroll实现左右联动滑动页面
Jun 30 Javascript
vue+Element-ui前端实现分页效果
Nov 15 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 smarty 二级分类代码和模版循环例子
2011/06/16 PHP
PHP用户注册邮件激活账户的实现代码
2017/05/31 PHP
Laravel接收前端ajax传来的数据的实例代码
2017/07/20 PHP
如何通过Apache在本地配置多个虚拟主机
2020/07/29 PHP
WordPress 照片lightbox效果的运用几点
2009/06/22 Javascript
Javascript 圆角div的实现代码
2009/10/15 Javascript
javascript实现的像java、c#之类的sleep暂停的函数代码
2010/03/04 Javascript
JS 有名函数表达式全面解析
2010/03/19 Javascript
javascript中的self和this用法小结
2014/02/08 Javascript
Javascript实现获取窗口的大小和位置代码分享
2014/12/04 Javascript
jQuery之DOM对象和jQuery对象的转换与区别分析
2015/01/08 Javascript
js在指定位置增加节点函数insertBefore()用法实例
2015/01/12 Javascript
jquery+ajax实现跨域请求的方法
2015/01/20 Javascript
javascript制作幻灯片(360度全景图片)
2015/07/28 Javascript
js倒计时简单实现代码
2016/08/11 Javascript
基于React实现表单数据的添加和删除详解
2017/03/14 Javascript
JavaScript实现选中文字提示新浪微博分享效果
2017/06/15 Javascript
Vue单文件组件基础模板小结
2017/08/10 Javascript
nodejs结合Socket.IO实现的即时通讯功能详解
2018/01/12 NodeJs
如何用RxJS实现Redux Form
2018/12/29 Javascript
vue实现将一个数组内的相同数据进行合并
2019/11/07 Javascript
[02:44]完美大师赛主赛事淘汰赛第二日观众采访
2017/11/24 DOTA
python+matplotlib绘制3D条形图实例代码
2018/01/17 Python
NumPy 数学函数及代数运算的实现代码
2018/07/18 Python
详解Python 调用C# dll库最简方法
2019/06/20 Python
tensorflow实现tensor中满足某一条件的数值取出组成新的tensor
2020/01/04 Python
Python常用库大全及简要说明
2020/01/17 Python
Python判断字符串是否为空和null方法实例
2020/04/26 Python
django中related_name的用法说明
2020/05/20 Python
Django中ORM找出内容不为空的数据实例
2020/05/20 Python
python 如何引入协程和原理分析
2020/11/30 Python
仓管岗位职责范本
2014/02/08 职场文书
公司寄语大全
2014/04/10 职场文书
我的中国梦主题教育活动总结
2015/05/07 职场文书
维护民族团结心得体会2016
2016/01/15 职场文书
使用canvas实现雪花飘动效果的示例代码
2021/03/30 HTML / CSS