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 相关文章推荐
利用jQuery插件扩展识别浏览器内核与外壳的类型和版本的实现代码
Oct 22 Javascript
jquery 中ajax执行的优先级
Jun 22 Javascript
JavaScript中Date对象的常用方法示例
Oct 24 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
Mar 08 Javascript
Vue通过input筛选数据
Oct 26 Javascript
javascript按钮禁用和启用的效果实例代码
Oct 29 Javascript
mui back 返回刷新页面的实例
Dec 06 Javascript
详解vue-admin和后端(flask)分离结合的例子
Feb 12 Javascript
Angular5给组件本身的标签添加样式class的方法
Apr 07 Javascript
Vue+axios实现统一接口管理的方法
Jul 23 Javascript
面试题:react和vue的区别分析
Apr 08 Javascript
vue-amap根据地址回显地图并mark的操作
Nov 03 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写的带缓存数据功能的mysqli类
2012/09/06 PHP
对于ThinkPHP框架早期版本的一个SQL注入漏洞详细分析
2014/07/04 PHP
PHP获取数组中指定的一列实例
2017/12/27 PHP
一个对于Array的简单扩展
2006/10/03 Javascript
JavaScript触发器详解
2007/03/10 Javascript
jquery 实现的全选和反选
2009/04/15 Javascript
跨浏览器开发经验总结(四) 怎么写入剪贴板
2010/05/13 Javascript
window.onload和$(function(){})的区别介绍
2013/10/30 Javascript
jQuery中ajax的使用与缓存问题的解决方法
2013/12/19 Javascript
IE6-IE9使用JSON、table.innerHTML所引发的问题
2015/12/22 Javascript
jQuery学习笔记之回调函数
2016/08/15 Javascript
js获取时间函数及扩展函数的方法
2016/10/30 Javascript
JavaScript实现图片本地预览功能【不用上传至服务器】
2017/09/20 Javascript
js判断数组是否包含某个字符串变量的实例
2017/11/24 Javascript
基于vue-resource jsonp跨域问题的解决方法
2018/02/03 Javascript
vue.js 获取select中的value实例
2018/03/01 Javascript
浅谈webpack 自动刷新与解析
2018/04/09 Javascript
jquery.pager.js分页实现详解
2019/07/29 jQuery
Postman参数化实现过程及原理解析
2020/08/13 Javascript
解析Python中的变量、引用、拷贝和作用域的问题
2015/04/07 Python
Python的网络编程库Gevent的安装及使用技巧
2016/06/24 Python
Python之日期与时间处理模块(date和datetime)
2017/02/16 Python
Python使用sftp实现上传和下载功能(实例代码)
2017/03/14 Python
Python爬取十篇新闻统计TF-IDF
2018/01/03 Python
Python SqlAlchemy动态添加数据表字段实例解析
2018/02/07 Python
python调用java的jar包方法
2018/12/15 Python
python中import与from方法总结(推荐)
2019/03/21 Python
解决yum对python依赖版本问题
2019/07/05 Python
python+openCV调用摄像头拍摄和处理图片的实现
2019/08/06 Python
Python web框架(django,flask)实现mysql数据库读写分离的示例
2020/11/18 Python
澳大利亚墨尔本的在线时装店:LORETA
2018/09/14 全球购物
寻找完美的房车租赁:RVShare
2019/02/23 全球购物
Big Green Smile法国:领先的英国有机和天然产品在线商店
2021/01/02 全球购物
计划生育责任书
2015/05/09 职场文书
React + Threejs + Swiper 实现全景图效果的完整代码
2021/06/28 Javascript
Linux在两个服务器直接传文件的操作方法
2022/08/05 Servers