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 相关文章推荐
巧妙破除网页右键禁用的十大绝招
Aug 12 Javascript
如何做到打开一个页面,过几分钟自动转到另一页面
Apr 20 Javascript
基于Jquery的将DropDownlist的选中值赋给label的实现代码
May 06 Javascript
js获取class的所有元素
Mar 28 Javascript
JavaScript实现页面实时显示当前时间的简单实例
Jul 20 Javascript
$.get获取一个文件的内容示例代码
Sep 11 Javascript
JS中实现replaceAll的方法(实例代码)
Nov 12 Javascript
jQuery实现类似老虎机滚动抽奖效果
Aug 06 Javascript
javascript封装addLoadEvent实现页面同时加载执行多个函数的方法
Jul 25 Javascript
Vue.js实现一个漂亮、灵活、可复用的提示组件示例
Mar 17 Javascript
微信小程序 http请求的session管理
Jun 07 Javascript
一秒学会微信小程序制作table表格
Feb 14 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来处理多个提交任务
2006/10/09 PHP
PHP小技巧之函数重载
2014/06/02 PHP
javascript 学习之旅 (2)
2009/02/05 Javascript
JavaScript初学者需要了解10个小技巧
2010/08/25 Javascript
bootstrap和jQuery.Gantt的css冲突 如何解决
2016/05/29 Javascript
Vue实现搜索 和新闻列表功能简单范例
2018/03/16 Javascript
使用Vue实现图片上传的三种方式
2018/07/17 Javascript
玩转vue的slot内容分发
2018/09/22 Javascript
layui表格数据重载
2019/07/27 Javascript
vue router 传参获取不到的解决方式
2019/11/13 Javascript
JavaScript Reflect Metadata实现详解
2019/12/12 Javascript
JavaScript canvas实现跟随鼠标事件
2020/02/10 Javascript
JS求解两数之和算法详解
2020/04/28 Javascript
python中的break、continue、exit()、pass全面解析
2017/08/05 Python
python将一组数分成每3个一组的实例
2018/11/14 Python
Python figure参数及subplot子图绘制代码
2020/04/18 Python
python根据用户需求输入想爬取的内容及页数爬取图片方法详解
2020/08/03 Python
Python操作Excel的学习笔记
2021/02/18 Python
CSS中越界问题的经典解决方案【推荐】
2016/04/19 HTML / CSS
video实现有声音自动播放的实现方法
2020/05/20 HTML / CSS
德国宠物用品、宠物食品及水族馆网上商店:ZooRoyal
2017/07/09 全球购物
新西兰演唱会和体育门票网站:Ticketmaster新西兰
2017/10/07 全球购物
大码女装:Ulla Popken
2019/08/06 全球购物
美国手机支架公司:PopSockets
2019/11/27 全球购物
若通过ObjectOutputStream向一个文件中多次以追加方式写入object,为什么用ObjectInputStream读取这些object时会产生StreamCorruptedException?
2016/10/17 面试题
化工机械应届生求职信
2013/11/04 职场文书
机电一体化大学生求职信
2013/11/08 职场文书
创业计划书怎样才能打动风投
2014/01/01 职场文书
优秀经理获奖感言
2014/03/04 职场文书
爱心捐款倡议书
2014/04/14 职场文书
毕业生代领毕业材料的授权委托书
2014/09/29 职场文书
名人传读书笔记
2015/06/26 职场文书
表扬稿表扬信的格式及范文
2019/06/24 职场文书
SpringBoot集成Redis,并自定义对象序列化操作
2021/06/22 Java/Android
Python软件包安装的三种常见方法
2022/07/07 Python
vue3 自定义图片放大器效果的示例代码
2022/07/23 Vue.js