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 相关文章推荐
利用js跨页面保存变量做菜单的方法
Jan 17 Javascript
ajax 文件上传应用简单实现
Mar 03 Javascript
fireworks菜单生成器mm_menu.js在 IE 7.0 显示问题的解决方法
Oct 20 Javascript
jquery1.83 之前所有与异步列队相关的模块详细介绍
Nov 13 Javascript
javascript动态创建及删除元素的方法
Dec 22 Javascript
Node.js 学习笔记之简介、安装及配置
Mar 03 Javascript
JavaScript中操作字符串小结
May 04 Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
Apr 14 jQuery
11行JS代码制作二维码生成功能
Mar 09 Javascript
bootstrap中selectpicker下拉框使用方法实例
Mar 22 Javascript
vue使用ElementUI时导航栏默认展开功能的实现
Jul 04 Javascript
深入分析JavaScript 事件循环(Event Loop)
Jun 19 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
Linux下编译redis和phpredis的方法
2016/04/07 PHP
php仿微信红包分配算法的实现方法
2016/05/13 PHP
屏蔽PHP默认设置中的Notice警告的方法
2016/05/20 PHP
PHP安装BCMath扩展的方法
2019/02/13 PHP
php+mysql开发中的经验与常识小结
2019/03/25 PHP
在网页中屏蔽快捷键
2006/09/06 Javascript
javascript 动态调整图片尺寸实现代码
2009/12/28 Javascript
js Date自定义函数 延迟脚本执行
2010/03/10 Javascript
nodejs实现获取某宝商品分类
2015/05/28 NodeJs
浅析JavaScript函数的调用模式
2016/08/10 Javascript
jQuery动态添加与删除tr行实例代码
2016/10/18 Javascript
基于Bootstrap和jQuery构建前端分页工具实例代码
2016/11/23 Javascript
JavaScript自定义浏览器滚动条兼容IE、 火狐和chrome
2017/01/05 Javascript
Vue.js手风琴菜单组件开发实例
2017/05/16 Javascript
vue 封装自定义组件之tabal列表编辑单元格组件实例代码
2017/09/07 Javascript
Vue中的v-for循环key属性注意事项小结
2018/08/12 Javascript
使用weixin-java-tools完成微信授权登录、微信支付的示例
2018/09/26 Javascript
面试题:react和vue的区别分析
2019/04/08 Javascript
深入理解python中的select模块
2017/04/23 Python
Python中 map()函数的用法详解
2018/07/10 Python
python+selenium实现自动化百度搜索关键词
2019/06/03 Python
使用python-opencv读取视频,计算视频总帧数及FPS的实现
2019/12/10 Python
Python logging日志库空间不足问题解决
2020/09/14 Python
使用HTML5中的contentEditable来将多行文本自动增高
2016/03/01 HTML / CSS
HTML5 HTMLCollection和NodeList的区别详解
2020/04/29 HTML / CSS
野兽派官方旗舰店:THE BEAST 野兽派
2016/08/05 全球购物
Ruby如何进行文件操作
2014/07/17 面试题
代理协议书
2014/04/22 职场文书
优秀团员事迹材料1000字
2014/08/20 职场文书
公安交警中队队长个人对照检查材料思想汇报
2014/10/05 职场文书
党性分析材料格式
2014/12/19 职场文书
房产公证书格式
2015/01/26 职场文书
2015年小学一年级班主任工作总结
2015/05/21 职场文书
护士爱岗敬业心得体会
2016/01/25 职场文书
Nginx 根据URL带的参数转发的实现
2021/04/01 Servers
python 如何执行控制台命令与操作剪切板
2021/05/20 Python