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自定义DateDiff函数(兼容所有浏览器)
Mar 01 Javascript
Javascript实现返回上一页面并刷新的小例子
Dec 11 Javascript
jQuery设置与获取HTML,文本和值的简单实例
Feb 26 Javascript
JavaScript截断字符串的方法
Jul 15 Javascript
设计模式中的facade外观模式在JavaScript开发中的运用
May 18 Javascript
jQuery源码解读之extend()与工具方法、实例方法详解
Mar 30 jQuery
React学习笔记之条件渲染(一)
Jul 02 Javascript
图文讲解用vue-cli脚手架创建vue项目步骤
Feb 12 Javascript
JavaScript一元正号运算符示例代码
Jun 30 Javascript
Vue Router 实现动态路由和常见问题及解决方法
Mar 06 Javascript
js代码实现轮播图
May 04 Javascript
js动态添加带圆圈序号列表的实例代码
Feb 18 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连mysql和oracle数据库性能比较
2006/10/09 PHP
Codeigniter里的无刷新上传的实现代码
2019/04/14 PHP
laravel 获取当前url的别名方法
2019/10/11 PHP
容易被忽略的JS脚本特性
2011/09/13 Javascript
Jquery submit()无法提交问题
2013/04/21 Javascript
jQuery 隐藏和显示 input 默认值示例
2014/06/03 Javascript
jQuery实现响应鼠标背景变化的动态菜单效果代码
2015/08/27 Javascript
JS显示日历和天气的方法
2016/03/01 Javascript
10分钟掌握XML、JSON及其解析
2020/12/06 Javascript
Bootstrap CSS布局之图像
2016/12/17 Javascript
jquery操作select取值赋值与设置选中实例
2017/02/28 Javascript
JS实现的全排列组合算法示例
2017/10/09 Javascript
JS实现将链接生成二维码并转为图片的方法
2018/03/17 Javascript
浅谈Vue CLI 3结合Lerna进行UI框架设计
2019/04/14 Javascript
vue2.0基于vue-cli+element-ui制作树形treeTable
2019/04/30 Javascript
详解element-ui中表单验证的三种方式
2019/09/18 Javascript
Vue.js页面中有多个input搜索框如何实现防抖操作
2019/11/04 Javascript
[52:22]EG vs VG Supermajor小组赛B组 BO3 第一场 6.2
2018/06/03 DOTA
python使用xauth方式登录饭否网然后发消息
2014/04/11 Python
PyQt5 pyqt多线程操作入门
2018/05/05 Python
opencv python 2D直方图的示例代码
2018/07/20 Python
python实现图片彩色转化为素描
2019/01/15 Python
解决使用PyCharm时无法启动控制台的问题
2019/01/19 Python
python 搜索大文件的实例代码
2019/07/08 Python
Python安装tar.gz格式文件方法详解
2020/01/19 Python
基于TensorBoard中graph模块图结构分析
2020/02/15 Python
Python绘图之二维图与三维图详解
2020/08/04 Python
特步官方商城:Xtep
2017/03/21 全球购物
业务经理岗位职责
2013/11/11 职场文书
新年团拜会主持词
2014/04/02 职场文书
贷款委托书怎么写
2014/08/02 职场文书
2014医学院领导班子对照检查材料思想汇报
2014/09/19 职场文书
学习党的群众路线教育实践活动剖析材料
2014/10/13 职场文书
校长新学期寄语2016
2015/12/04 职场文书
干货:如何写好观后感 !
2019/05/21 职场文书
Hive常用日期格式转换语法
2022/06/25 数据库