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 相关文章推荐
document.documentElement &amp;&amp; document.documentElement.scrollTop
Dec 01 Javascript
Jquery 点击按钮显示和隐藏层的代码
Jul 25 Javascript
jQuery中:first选择器用法实例
Dec 30 Javascript
jQuery 1.9.1源码分析系列(十)事件系统之主动触发事件和模拟冒泡处理
Nov 24 Javascript
Bootstrap每天必学之日期控制
Mar 07 Javascript
AngularJS基础 ng-selected 指令简单示例
Aug 03 Javascript
jquery中用jsonp实现搜索框功能
Oct 18 Javascript
jQuery加密密码到cookie的实现代码
Apr 18 jQuery
详解axios 全攻略之基本介绍与使用(GET 与 POST)
Sep 15 Javascript
elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo
Jul 03 Javascript
JsonProperty 的使用方法详解
Oct 11 Javascript
基于Angular 8和Bootstrap 4实现动态主题切换的示例代码
Feb 11 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
某大型网络公司应聘时的笔试题目附答案
2008/03/27 PHP
php 获取完整url地址
2008/12/20 PHP
开启CURL扩展,让服务器支持PHP curl函数(远程采集)
2011/03/19 PHP
php过滤XSS攻击的函数
2013/11/12 PHP
php5.3不能连接mssql数据库的解决方法
2014/12/27 PHP
简单了解WordPress开发中update_option()函数的用法
2016/01/11 PHP
PHP设置Cookie的HTTPONLY属性方法
2017/02/09 PHP
JavaScript 入门·JavaScript 具有全范围的运算符
2007/10/01 Javascript
JMenuTab简单使用说明
2008/03/13 Javascript
刷新页面实现方式总结(HTML,ASP,JS)
2008/11/13 Javascript
Extjs表单常见验证小结
2014/03/07 Javascript
javascript中一些util方法汇总
2015/06/10 Javascript
Jquery Mobile 自定义按钮图标
2015/11/18 Javascript
node.js 中国天气预报 简单实现
2016/06/06 Javascript
JavaScript中的this使用详解
2016/07/27 Javascript
前端面试知识点锦集(JavaScript篇)
2016/12/28 Javascript
jQuery插件echarts设置折线图中折线线条颜色和折线点颜色的方法
2017/03/03 Javascript
微信小程序 合法域名校验出错详解及解决办法
2017/03/09 Javascript
彻底学会Angular.js中的transclusion
2017/03/12 Javascript
快速使用node.js进行web开发详解
2017/04/26 Javascript
js实现日期显示的一些操作(实例讲解)
2017/07/27 Javascript
VUE 解决mode为history页面为空白的问题
2019/11/01 Javascript
Python中处理字符串之endswith()方法的使用简介
2015/05/18 Python
详解windows python3.7安装numpy问题的解决方法
2018/08/13 Python
Jupyter Notebook的连接密码 token查询方式
2020/04/21 Python
新闻记者个人求职的自我评价
2013/11/28 职场文书
美术教师自我鉴定
2014/02/12 职场文书
给公司的建议书范文
2014/05/13 职场文书
医院搬迁方案
2014/06/14 职场文书
国际贸易求职信
2014/07/05 职场文书
公共机构节能宣传周活动总结
2014/07/09 职场文书
卫生院义诊活动总结
2015/05/07 职场文书
西游记读书笔记
2015/06/25 职场文书
python-opencv 中值滤波{cv2.medianBlur(src, ksize)}的用法
2021/06/05 Python
Python实现简单的俄罗斯方块游戏
2021/09/25 Python
Python实现视频自动打码的示例代码
2022/04/08 Python