AngularJS:如何在页面完全加载之前显示预加载或加载?
Posted
技术标签:
【中文标题】AngularJS:如何在页面完全加载之前显示预加载或加载?【英文标题】:AngularJS: How to show preload or loading until page is loaded completely? 【发布时间】:2016-01-06 22:27:24 【问题描述】:我有一个图片库网站,我在我的控制器中以 json 格式从数据库中获取所有图像和图像相关数据,然后通过使用 ng-repeat 我将它们与 html 绑定。现在,数据加载较早,但图像加载较晚,因此图像分散。如何解决这个问题。我不想使用 setTimeOut。
示例代码如下:-
<!DOCTYPE html>
<html lang="en" class="no-js" ng-app="cps">
<body ng-controller="CPSController">
<div>
<li ng-repeat="image in images" class="shown">
<a id="image.imageid" ng-click="openimage(image.imageid)">
<img idx="id-thumb-$index" ng-src="/imagedisplay/image.imageid" style="">
<div class="meta_info">
<h3>image.imagename.</h3>
<div class="callto">
<div class="actions">
<span><img src="img/artist.svg" >image.ownername</span>
<span><img src="img/likes.svg" >image.likes</span>
<span><img src="img/views_small.svg" >image.views</span>
</div>
<div class="category">
Art Category
</div>
</div>
</div>
</a>
</li>
</div>
</body>
</html>
<script>
var cps = angular.module('cps', []);
cps.controller('CPSController', function($scope, $http, $compile)
$scope.products = [];
$http.get("/alldata/").success(function(data)
if(data != "null")
for(i=data.length-1; i>=0; i--)
$scope.products.push(data[i]);
$scope.sendOrder('views', 'likes', 'timestamp', 2);
else
//$('#noImages').show();
/*setTimeout(function()
$("[idx^='id-thumb']").show();
);*/
);
);
</script>
【问题讨论】:
【参考方案1】:# UPDATE [August 2017]
除了我们可以使用window
上的load
事件而不是DOMContentLoaded
上的DOMContentLoaded
之外,答案与以下相同。这将确保window
中的所有资产(例如图像)都加载。
window.addEventListener("load", function(event)
...
)
我们不必在 vanilla javascript
可以满足的情况下强制使用 Angular。这就是我的AngularJS
项目的工作原理
将此添加到正文标记中。一旦 HTML 内容加载,它将使用脚本标记删除
<div id="page-loading">
<img style="display:block; margin:0 auto;" src="styles/img/page-loading.gif">
</div>
script
图片正下方的标签。
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event)
/*VANILLA JAVASCRIPT*/
var element = document.getElementById("page-loading");
element.parentNode.removeChild(element);
/* OR WITH jQuery*/
$('#page-loading')
.fadeOut('slow');
);
</script>
DOMContentLoaded
事件 将确保在所有images,fonts,js and other assets
都已加载后执行callback
。
祝你好运。
【讨论】:
绝妙的解决方案!即使我们在 Angular 中使用 ng-cloak,当 Angular 需要时间来引导应用程序时,第一次加载仍然需要这样做。【参考方案2】:我不确定这是否是正确的方法,但我通常做的是我有一个具有页面状态的$scope.loaded
变量。如果页面已加载,则会显示您要显示的 div...如果正在加载,则会显示带有加载程序的 div。看看这个plunk 了解我想说的话。
我也在此处粘贴 Plunkr 代码。
Javascript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout)
$scope.loaded = true;
$scope.text = 'Nothing loaded yet.';
$scope.loadSomething = function ()
$scope.loaded = false;
$timeout(function()
// Simulates loading
$scope.text = 'Hello World';
$scope.loaded = true;
, 2000);
;
);
HTML
<body ng-controller="MainCtrl">
<button class="btn btn-primary" ng-click="loadSomething()">Load Something</button>
<br/>
<div ng-hide="loaded">
Loading...
</div>
<div ng-show="loaded">
<p> text </p>
</div>
如果您需要任何进一步的帮助,请告诉我。
【讨论】:
【参考方案3】:试试这个:
angular.element($window).bind('load', function()
$scope.yourLoaderDiv=true;
);
【讨论】:
【参考方案4】:我一直在为同样的问题而苦苦挣扎。这是我这边的工作,我根据承诺为每个不同的部分显示多个加载图像。为此,我创建了一个指令。
我的 html 如下所示。
<mi-loading promise="Loading"></mi-loading>
Angularjs 指令。
(function ()
var module = angular.module('mi-loading', []);
module.directive('miLoading', function ()
return
restrict: 'E',
scope:
promise: '='
,
link: function ($scope, $element, $attrs)
$scope.IsLoading = true;
$scope.$watch('promise', function (prom)
if (!prom)
$scope.IsLoading = false;
return;
prom.success(function () $scope.IsLoading = false; );
);
,
template: '<div ng-show="IsLoading" class="spinner" style="height:300px"></div>'
;
);
)();
最后是用法,
var getData = function ()
var Promise = myservice.getMyData($scope);
$scope.Loading = Promise;
;
CSS
.spinner
min-width: 30px;
min-height: 30px;
.spinner:before
content: 'Loading…';
position: absolute;
top: 50%;
left: 50%;
width: 24px;
height: 24px;
margin-top: -13px;
margin-left: -13px;
.spinner:not(:required):before
content: '';
border-radius: 50%;
border: 3px solid #ccc;
/*border-top-color: #03ade0;*/
border-top-color: #4187b5;
animation: spinner .6s linear infinite;
-webkit-animation: spinner .6s linear infinite;
【讨论】:
【参考方案5】:为了实现它,我将所有脚本加载到正文的末尾。 在我的 app-wrapper-div 之前,我放置了一个固定的“加载”-div。它会在加载其他脚本之前立即显示。
在正文的末尾,包含我的脚本后,我放置了一个 angular 指令,即淡出并删除 loading-div。
代码:
<html ng-app="myApp">
<head>
<!-- the only file loaded in the head -->
<link rel="stylesheet" href="/.../appLoadingScreen.css"/>
</head>
<body>
<div id="appLoadingScreen">
<div id="appLoadingScreenCenterWrap">
<h1 id="appLoadingScreenHeader">APP TITLE</h1>
<p id="appLoadingScreenMsg">App is loading!</p>
</div>
</div>
<div id="appWrapper" ng-controller="appCtrl">
...
</div>
<!-- All stylesheet includes -->
...
<!-- All script includes -->
...
<script src="/.../hideLoadingScreen.js"></script>
<hide-loading-screen></hide-loading-screen>
</body>
</html>
还有 hideLoadingScreen 指令:
(function()
var app = angular.module('appModule');
app.directive('hideLoadingScreen', function($timeout)
return
restrict: 'E',
link: function()
$timeout(function()
$("#appLoadingScreen").fadeOut(600, function()$(this).remove(););
, 400);
;
);
)();
【讨论】:
【参考方案6】:虽然@chotesah 的回答恰到好处,但我可以建议您另辟蹊径,为每张图片使用预加载器(类似于 Facebook 页面加载)。
试试这个module。 您需要更改几行:
// Add module dependency
angular.module('app', ['angular-preload-image']);
…
<img preload-image idx="id-thumb-$index" ng-src="/imagedisplay/image.imageid" default-image="[URL]" fallback-image="[URL]" />
然后在codrops 寻找漂亮的图像预加载器。
【讨论】:
以上是关于AngularJS:如何在页面完全加载之前显示预加载或加载?的主要内容,如果未能解决你的问题,请参考以下文章