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 相关文章推荐
Google排名中的10个最著名的 JavaScript库
Apr 27 Javascript
ExtJs事件机制基本代码模型和流程解析
Oct 24 Javascript
jQuery实现的Div窗口震动特效
Jun 09 Javascript
javascript常用的方法分享
Jul 01 Javascript
JavaScript多线程详解
Aug 12 Javascript
Layui table 组件的使用之初始化加载数据、数据刷新表格、传参数
Sep 11 Javascript
深入浅析Vue中的Prop
Jun 10 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
Oct 08 Javascript
vue项目打包之后背景样式丢失的解决方案
Jan 17 Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
Mar 21 Javascript
在layer弹层layer.prompt中,修改placeholder的实现方法
Sep 27 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
Dec 02 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网站基础优化方法小结
2008/09/29 PHP
php urlencode()与urldecode()函数字符编码原理详解
2011/12/06 PHP
8个PHP数组面试题
2015/06/23 PHP
PHP中Laravel 关联查询返回错误id的解决方法
2017/04/01 PHP
基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作
2020/08/17 PHP
js中设置元素class的三种方法小结
2011/08/28 Javascript
基于jquery自己写tab滑动门(通用版)
2012/10/30 Javascript
jquery中选择块并改变属性值的方法
2013/07/31 Javascript
Jquery Ajax方法传值到action的方法
2014/05/11 Javascript
JavaScript获取表单内所有元素值的方法
2015/04/02 Javascript
jQuery基于ajax实现带动画效果无刷新柱状图投票代码
2015/08/10 Javascript
javascript实现的左右无缝滚动效果
2016/09/19 Javascript
强大的 Angular 表单验证功能详细介绍
2017/05/23 Javascript
解决ionic和angular上拉加载的问题
2017/08/03 Javascript
JS动态添加元素及绑定事件造成程序重复执行解决
2017/12/07 Javascript
Vue2.0学习系列之项目上线的方法步骤(图文)
2018/09/25 Javascript
JavaScript检查数据中是否存在相同的元素(两种方法)
2018/10/07 Javascript
微信小程序实现工作时间段选择
2019/02/15 Javascript
[03:34]2014DOTA2西雅图国际邀请赛 淘汰赛7月15日TOPPLAY
2014/07/15 DOTA
初学python数组的处理代码
2011/01/04 Python
Python中的map、reduce和filter浅析
2014/04/26 Python
Python import与from import使用及区别介绍
2018/09/06 Python
2019 Python最新面试题及答案16道题
2019/04/11 Python
python实现把二维列表变为一维列表的方法分析
2019/10/08 Python
pandas 缺失值与空值处理的实现方法
2019/10/12 Python
Python jieba库用法及实例解析
2019/11/04 Python
Python模块的定义,模块的导入,__name__用法实例分析
2020/01/07 Python
浅谈Django中的QueryDict元素为数组的坑
2020/03/31 Python
乐高积木玩具美国官网:LEGO Shop US
2016/09/16 全球购物
生产部厂长助理职位说明书
2014/03/03 职场文书
公司运动会策划方案
2014/05/25 职场文书
2015新年联欢晚会开场白
2014/12/14 职场文书
回门宴新娘答谢词
2015/09/29 职场文书
导游词之包公祠
2019/11/25 职场文书
mybatis 获取无数据的字段不显示的问题
2021/07/15 Java/Android
浅谈Python3中datetime不同时区转换介绍与踩坑
2021/08/02 Python