Javascript AngularJS:如何在页面完全加载之前显示预加载或加载?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33030360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS: How to show preload or loading until page is loaded completely?
提问by Anirban Datta
I've an image gallery site where I'm getting all images and image related data from the database as json format in my controller and then by using ng-repeat I'm binding them with the html. Now, data are loaded early but images are loaded late, so images are scattered. How to solve this. I don't want to use setTimeOut.
我有一个图片库站点,我从数据库中获取所有图像和图像相关数据作为控制器中的 json 格式,然后通过使用 ng-repeat 我将它们与 html 绑定。现在,数据加载较早,但图像加载较晚,因此图像分散。如何解决这个问题。我不想使用 setTimeOut。
The sample code is as below:-
示例代码如下:-
<!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}}" alt="" style="">
<div class="meta_info">
<h3>{{image.imagename}}.</h3>
<div class="callto">
<div class="actions">
<span><img src="img/artist.svg" alt="">{{image.ownername}}</span>
<span><img src="img/likes.svg" alt="">{{image.likes}}</span>
<span><img src="img/views_small.svg" alt="">{{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>
回答by Akash
# UPDATE [August 2017]
# UPDATE [August 2017]
Same answer as below except we could work with the load
event on window
instead of DOMContentLoaded
on document
. This will ensure that all assets (such as images) in the window
are loaded.
与下面相同的答案,除了我们可以使用load
onwindow
而不是DOMContentLoaded
on事件document
。这将确保在所有资产(如图像)window
被加载。
window.addEventListener("load", function(event) {
...
})
We don't have to force Angular where vanilla javascript
can suffice. This is how it worked for my AngularJS
project
我们不必强制 Angularvanilla javascript
就足够了。这就是它对我的AngularJS
项目的工作方式
Added this to the body tag. It will be removed with a script tag once HTML Content Loads
将此添加到 body 标签中。HTML 内容加载后,它将使用脚本标记删除
<div id="page-loading">
<img style="display:block; margin:0 auto;" src="styles/img/page-loading.gif">
</div>
script
tag right under the image.
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
eventwill ensure that the the callback
is executed when all the images,fonts,js and other assets
have been loaded.
DOMContentLoaded
事件将确保callback
在所有images,fonts,js and other assets
已加载后执行。
Good Luck.
祝你好运。
回答by Haseeb Ahmed
I'm not sure if this is the right approach, but what I usually do is that I have a $scope.loaded
variable which has the state of the page. If the page is loaded, the div you want to show is shown... If it's loading, the div with the loader is shown. Have a look at this plunkto get what I'm trying to say.
我不确定这是否是正确的方法,但我通常做的是我有一个$scope.loaded
包含页面状态的变量。如果页面已加载,则会显示您要显示的 div... 如果正在加载,则会显示带有加载程序的 div。看看这个plunk来了解我想说的话。
I'm pasting the Plunkr code here as well.
我也在此处粘贴 Plunkr 代码。
Javascript
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
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>
Do let me know if you need any further help.
如果您需要任何进一步的帮助,请告诉我。
回答by vineet
Try this:
尝试这个:
angular.element($window).bind('load', function() {
$scope.yourLoaderDiv=true;
});
回答by terales
While @chotesah answer is just right I can suggest you go another way and use preloaders for each image (something like Facebook on page load).
虽然@chotesah 的答案恰到好处,但我建议您采用另一种方式,为每个图像使用预加载器(例如页面加载时的 Facebook)。
Try this module. You'll need to change few lines:
试试这个模块。您需要更改几行:
// 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]" />
After that look for nifty image preloaders at codrops.
回答by J-D
I have struggled with same issue. Here is what working on my side where i am showing multiple loading image for each different section based on promise. For this purpose i have created a directive.
我一直在努力解决同样的问题。这是我这边的工作,我根据承诺为每个不同的部分显示多个加载图像。为此,我创建了一个指令。
My html looks something like below.
我的 html 如下所示。
<mi-loading promise="Loading"></mi-loading>
Angularjs directive.
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>'
};
});
})();
and finally the usage,
最后是用法,
var getData = function ()
{
var Promise = myservice.getMyData($scope);
$scope.Loading = Promise;
};
CSS
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;
}
回答by Ruwen
To achieve it, i am loading all my scripts at the end of the body. Before my app-wrapper-div i place a postion fixed "loading"-div. It is shown immediately before other scripts are loaded.
为了实现它,我在正文的末尾加载了所有脚本。在我的 app-wrapper-div 之前,我放置了一个位置固定的“加载”-div。它在加载其他脚本之前立即显示。
At the end of the body, after my scripts are included, i place an angular directive, that fadeOut and remove the loading-div.
在正文的末尾,在包含我的脚本后,我放置了一个 angular 指令,即淡出并删除加载 div。
The code:
编码:
<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>
And the hideLoadingScreen directive:
和 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);
}
};
});
})();