我正在使用ui-router作为我的角应用程序。我有一些包含图像的视图。我希望角度加载条也可以在这些图像加载完成后进行跟踪。或者更一般地说,直到视图完成渲染。
当我偶然发现post关于如何使用angularJS进行搜索引擎优化时,它表明我们必须创建每个“页面”的静态html快照,并将它们提供给搜索引擎机器人,以便可以对它们进行爬网。为此,我们必须使用无头浏览器爬行应用程序中的所有页面,并将html存储到将要提供的文件中。但是,由于角度必须加载ajax和所有的视图,我们必须等待我们的页面加载,然后存储无头浏览器的HTML。否则我们会得到空视图的空html。
我写了一个小脚本,可以检查我们的视图的就绪状态。当$ rootScope.status属性等于'ready'时,我知道我可以存储我的无头浏览器的html,因为它已经完成加载。
<Window x:Class="CountDown.CountDownDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CountDown"
mc:Ignorable="d"
Title="CountDownDisplay" Height="768" Width="1024" WindowState="Maximized" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">
<Grid Name="grid1">
<Image x:Name="vwbImage" Source="matematickyproud2015.png"/>
<Viewbox x:Name="vwbTime" Visibility="Hidden">
<TextBlock x:Name="txbTimeToEnd" Margin="2" Text="01:30:00" HorizontalAlignment="center" VerticalAlignment="center"/>
</Viewbox>
</Grid>
</Window>
然后,在我们的每个控制器中,我们必须调用
var app = angular.module("app", ["ui.router", 'ngAnimate','angular-loading-bar','angular-images-loaded','angular-google-analytics']);
app.run(['$rootScope', function($rootScope){
$rootScope.loadingCount = 0;
$rootScope.changeSuccess = false;
$rootScope.ready = function(){
$rootScope.loadingCount--;
if (($rootScope.loadingCount == 0) && ($rootScope.changeSuccess == true)){
$rootScope.status = 'ready';
}
};
$rootScope.loading = function(){
$rootScope.loadingCount++;
$rootScope.status = 'loading';
};
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
$rootScope.loadingCount = 0;
$rootScope.changeSuccess = false;
});
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
$rootScope.changeSuccess = true;
});
$rootScope.$on("$viewContentLoading", function(){
$rootScope.loadingCount++;
});
$rootScope.$on("$viewContentLoading", function(){
$rootScope.loadingCount--;
});
}]);
当控制器准备就绪时
$rootScope.loading();
有了这个,我们将能够检查我们所有的控制器是否都呈现了他们的观点。它现在不是超级优雅,但是它起到了作用。
此脚本可以与angular-load-bar很好地集成,因为它可以跟踪整个应用程序的准备情况。进度条可以是该进度的指标。这样做的缺点是它与角度加载条跟踪XHR请求的自然行为有冲突。
例如,在我的控制器中,我使用它:
$rootScope.ready()
此代码应该直接在$ rootScope脚本中迁移,该脚本跟踪视图的准备情况。
app.controller("WorksController", [
"$scope", "cfpLoadingBar",
function ($scope, cfpLoadingBar) {
cfpLoadingBar.start();
$scope.imgLoadedEvents = {
always: function () {
cfpLoadingBar.complete();
}
};
}
]);
虽然,角度进度条仍然在后台运行。我让激活XHR拦截器。但是,如果在加载图像之前完成XHR请求,则即使视图尚未完成,进度条也会消失。同样,如果在XHR请求完成之前加载了图像,则进度条会消失。
如何将角度加载条的XHR拦截功能与此视图准备拦截功能集成?
答案 0 :(得分:1)
在不修改angular-loaded-bar代码的情况下,这是不可能的,因为$ http拦截器没有你可以挂钩的任何API。
您应该在Github上分叉项目并修改cfb.loadingBarInterceptor
。基本上你需要做的就是删除隐藏的代码并显示加载栏。将代码留在$rootScope
上的广播事件中。这就是你要加入的内容。
return {
'request': function(config) {
// Check to make sure this request hasn't already been cached and that
// the requester didn't explicitly ask us to ignore this request:
if (!config.ignoreLoadingBar && !isCached(config)) {
$rootScope.$broadcast('cfpLoadingBar:loading', {url: config.url});
}
return config;
},
'response': function(response) {
if (!response || !response.config) {
$log.error('Broken interceptor detected: Config object not supplied in response:\n https://github.com/chieffancypants/angular-loading-bar/pull/50');
return response;
}
if (!response.config.ignoreLoadingBar && !isCached(response.config)) {
$rootScope.$broadcast('cfpLoadingBar:loaded', {url: response.config.url, result: response});
}
return response;
},
'responseError': function(rejection) {
if (!rejection || !rejection.config) {
$log.error('Broken interceptor detected: Config object not supplied in rejection:\n https://github.com/chieffancypants/angular-loading-bar/pull/50');
return $q.reject(rejection);
}
if (!rejection.config.ignoreLoadingBar && !isCached(rejection.config)) {
$rootScope.$broadcast('cfpLoadingBar:loaded', {url: rejection.config.url, result: rejection});
}
return $q.reject(rejection);
}
};
现在,在您的运行块中,只需在底部添加这些行:
app.run(['$rootScope', function($rootScope){
// Previous code ...
$rootScope.$on("cfbLoadingBar:loaded", $rootScope.ready);
$rootScope.$on("cfbLoadingBar:loading", $rootScope.loading);
});
如果不清楚这是做什么的,它会使用新的$ http拦截器中的事件,这会导致调用ready
和loading
的方式与控制器的调用方式相同
答案 1 :(得分:1)
您所指的博客帖子是遗产。
Google 将索引您的单页应用,不含任何html快照。
如果要创建快照(例如,使用尚不支持的规范标记!),则不应手动执行此操作,而应在构建过程中集成任务。使用Grunt / Gulp,这非常简单,可以在10分钟内完成。无需指定“就绪”事件 - phantomjs将识别脚本何时完成。
正确的方法是移动在状态下加载图像的功能解析功能。然后你不必担心将准备好的事件发送给幻像。 ;-)使用加载栏:
$rootScope.$on('$stateChangeStart', function () {
ngProgress.start();
// or your: cfpLoadingBar.start();
});
$rootScope.$on('$stateChangeSuccess', function () {
ngProgress.complete();
// or your: cfpLoadingBar.complete();
});
答案 2 :(得分:1)
正如@ anid-monsur指定的那样,如果不修改加载条代码就不可能做到。虽然,我想保留角度加载条的初始功能,所以我遵循他建议的不同路径。
我没有删除隐藏显示代码,而是在angular-loading-bar拦截器中添加了类似这样的自定义事件处理程序:
$rootScope.$on("cfpLoadingBar:customRequest", function(event, args){
if (!args) {
args = {};
}
if (!args.url){
args.url = 'custom';
}
loading(args);
});
$rootScope.$on("cfpLoadingBar:customResponse", function(event, args){
if (!args) {
args = {};
}
if (!args.config){
args.config = {};
}
if (!args.config.url){
args.config.url = 'custom';
}
response(args);
});
检查代码here
所以,当我的ui-router改变状态时,我可以写:
app.run(['$rootScope', 'cfpLoadingBar', function($rootScope, cfpLoadingBar){
$rootScope.$broadcast("cfpLoadingBar:customRequest");
$rootScope.ready = function(){
$rootScope.$broadcast("cfpLoadingBar:customResponse");
};
$rootScope.loading = function(){
$rootScope.$broadcast("cfpLoadingBar:customRequest");
};
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
$rootScope.$broadcast("cfpLoadingBar:customRequest");
});
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
$rootScope.$broadcast("cfpLoadingBar:customResponse");
});
}]);
注意添加的$ rootScope.ready()和$ rootScope.loading()
当控制器具有延迟加载过程时使用它们
例如,使用angular-imagesloaded:
app.controller("WorksController", [
"$scope", '$rootScope',
function ($scope, $rootScope) {
$rootScope.loading();
$scope.imgLoadedEvents = {
done: function () {
$rootScope.ready();
}
};
}
]);
这样,我仍然可以使用angular-load-bar提供的本机拦截器并注册我自己的&#34; custom&#34;要求。
答案 3 :(得分:0)
这个问题与插件有关,因为 Anid Monsur 说。您可以解决仅将angular-loading-bar
升级到最新版本或至少 7.0.1 + 的问题。