【发布时间】:2023-04-04 09:30:02
【问题描述】:
我有一个函数,我想在加载页面内容后调用它。我阅读了有关 $viewContentLoaded 的信息,但它对我不起作用。我正在寻找类似的东西
document.addEventListener('DOMContentLoaded', function () {
//Content goes here
}, false);
以上调用在 AngularJs 控制器中对我不起作用。
【问题讨论】:
我有一个函数,我想在加载页面内容后调用它。我阅读了有关 $viewContentLoaded 的信息,但它对我不起作用。我正在寻找类似的东西
document.addEventListener('DOMContentLoaded', function () {
//Content goes here
}, false);
以上调用在 AngularJs 控制器中对我不起作用。
【问题讨论】:
根据$viewContentLoaded 的文档,它应该可以工作
每次重新加载 ngView 内容时发出。
$viewContentLoaded 事件已发出,这意味着要接收此事件,您需要一个父控制器,例如
<div ng-controller="MainCtrl">
<div ng-view></div>
</div>
从MainCtrl你可以收听事件
$scope.$on('$viewContentLoaded', function(){
//Here your view content is fully loaded !!
});
查看Demo
【讨论】:
ng-repeat 和几个嵌套指令将根据复杂的循环和条件生成 HTML/内容时,此选项将不起作用。渲染会持续一段时间,即使在$viewContentLoaded 事件被触发之后。如何确保所有元素都已完全渲染然后执行某些代码?有什么反馈吗?
角度
angular.element(document).ready(function () {
console.log('page loading completed');
});
角度 >= 1.6.X
angular.element(function () {
console.log('page loading completed');
});
【讨论】:
像这样使用指令和角度元素ready 方法:
.directive( 'elemReady', function( $parse ) {
return {
restrict: 'A',
link: function( $scope, elem, attrs ) {
elem.ready(function(){
$scope.$apply(function(){
var func = $parse(attrs.elemReady);
func($scope);
})
})
}
}
})
<div elem-ready="someMethod()"></div>
或者对于那些使用 controller-as 语法的人...
<div elem-ready="vm.someMethod()"></div>
这样做的好处是,您可以根据自己的喜好对 UI 进行广泛或细化,并且您正在从控制器中删除 DOM 逻辑。我认为这是推荐的 Angular 方式。
如果您有其他指令在同一节点上运行,您可能需要优先考虑该指令。
【讨论】:
elem.ready( $scope.$apply( readyFunc( $scope ))); 窒息,任何想法为什么会这样?也许发生了对角度的更新?无论如何 - 如果可行的话,这是一种优雅的方法。
attrs.onReady 有错字,应该是现在的样子。另一个问题是我称它为时髦............我将咖啡脚本从内存转换为 JS 得到了什么。
$timeout,否则您将被困在控制器级别;您正在明确创建一个 addt。 DOM 节点简单地执行非 dom 逻辑;仅当该方法位于 $scope 层次结构中很远的位置以便子作用域继承它时,它才可重用;我只是认为从 NG 的角度来看它看起来很糟糕;
elem.ready() 周围添加$timeout(function() {}) 后为我工作。否则它会抛出 $digest already in progress 错误。但无论如何,非常感谢!在过去的一个小时里,我一直在为此苦苦挣扎。
可以直接在 HTML 元素后添加{{YourFunction()}} 调用。
这是Plunker Link。
【讨论】:
<div ng-init="yourFuction()"></div>,如Saad's answer所示
我必须在处理谷歌图表时实现这个逻辑。我所做的是在我添加的控制器定义中的 html 末尾。
<body>
-- some html here --
--and at the end or where ever you want --
<div ng-init="FunCall()"></div>
</body>
并在该函数中简单地调用您的逻辑。
$scope.FunCall = function () {
alert("Called");
}
【讨论】:
var myM = angular.module('data-module');
myM.directive('myDirect',['$document', function( $document ){
function link( scope , element , attrs ){
element.ready( function(){
} );
scope.$on( '$viewContentLoaded' , function(){
console.log(" ===> Called on View Load ") ;
} );
}
return {
link: link
};
}] );
以上方法对我有用
【讨论】:
您可以在 Angular js 中调用 javascript 版本的 onload 事件。此 ng-load 事件可以应用于任何 dom 元素,如 div、span、body、iframe、img 等。以下是在现有项目中添加 ng-load 的链接。
download ng-load for angular js
以下是 iframe 的示例,一旦加载 testCallbackFunction 将在控制器中调用
示例
JS
// include the `ngLoad` module
var app = angular.module('myApp', ['ngLoad']);
app.controller('myCtrl', function($scope) {
$scope.testCallbackFunction = function() {
//TODO : Things to do once Element is loaded
};
});
HTML
<div ng-app='myApp' ng-controller='myCtrl'>
<iframe src="test.html" ng-load callback="testCallbackFunction()">
</div>
【讨论】:
如果您收到 $digest already in progress 错误,这可能会有所帮助:
return {
restrict: 'A',
link: function( $scope, elem, attrs ) {
elem.ready(function(){
if(!$scope.$$phase) {
$scope.$apply(function(){
var func = $parse(attrs.elemReady);
func($scope);
})
}
else {
var func = $parse(attrs.elemReady);
func($scope);
}
})
}
}
【讨论】:
我在模板中使用了{{myFunction()}},但后来在控制器中使用$timeout 找到了另一种方式here。想我会分享它,对我很有用。
angular.module('myApp').controller('myCtrl', ['$timeout',
function($timeout) {
var self = this;
self.controllerFunction = function () { alert('controller function');}
$timeout(function () {
var vanillaFunction = function () { alert('vanilla function'); }();
self.controllerFunction();
});
}]);
【讨论】:
在页面加载后运行应该通过为窗口加载事件设置一个事件监听器来部分满足
window.addEventListener("load",function()...)
在 angular 的 module.run(function()...) 中,您将拥有对模块结构和依赖项的所有访问权限。
您可以使用broadcast 和emit 事件进行通信桥接。
例如:
【讨论】:
如果您希望某个元素完全加载,请在该元素上使用 ng-init。
例如<div class="modal fade" id="modalFacultyInfo" role="dialog" ng-init="initModalFacultyInfo()"> ..</div>
initModalFacultyInfo() 函数应该存在于控制器中。
【讨论】:
我发现如果您有嵌套视图 - 每个嵌套视图都会触发 $viewContentLoaded。我创建了这个解决方法来找到最终的 $viewContentLoaded。根据 Prerender 的要求设置 $window.prerenderReady 似乎可以正常工作(进入主 app.js 中的 .run() ):
// Trigger $window.prerenderReady once page is stable
// Note that since we have nested views - $viewContentLoaded is fired multiple
// times and we need to go around this problem
var viewContentLoads = 0;
var checkReady = function(previousContentLoads) {
var currentContentLoads = Number(viewContentLoads) + 0; // Create a local copy of the number of loads
if (previousContentLoads === currentContentLoads) { // Check if we are in a steady state
$window.prerenderReady = true; // Raise the flag saying we are ready
} else {
if ($window.prerenderReady || currentContentLoads > 20) return; // Runaway check
$timeout(function() {checkReady(currentContentLoads);}, 100); // Wait 100ms and recheck
}
};
$rootScope.$on('$stateChangeSuccess', function() {
checkReady(-1); // Changed the state - ready to listen for end of render
});
$rootScope.$on('$viewContentLoaded', function() {
viewContentLoads ++;
});
【讨论】:
var myTestApp = angular.module("myTestApp", []);
myTestApp.controller("myTestController", function($scope, $window) {
$window.onload = function() {
alert("is called on page load.");
};
});
【讨论】:
对我有用的解决方案如下
app.directive('onFinishRender', ['$timeout', '$parse', function ($timeout, $parse) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
if (!!attr.onFinishRender) {
$parse(attr.onFinishRender)(scope);
}
});
}
if (!!attr.onStartRender) {
if (scope.$first === true) {
$timeout(function () {
scope.$emit('ngRepeatStarted');
if (!!attr.onStartRender) {
$parse(attr.onStartRender)(scope);
}
});
}
}
}
}
}]);
控制器代码如下
$scope.crearTooltip = function () {
$('[data-toggle="popover"]').popover();
}
html代码如下
<tr ng-repeat="item in $data" on-finish-render="crearTooltip()">
【讨论】:
我使用setInterval 等待内容加载。我希望这可以帮助您解决这个问题。
var $audio = $('#audio');
var src = $audio.attr('src');
var a;
a = window.setInterval(function(){
src = $audio.attr('src');
if(src != undefined){
window.clearInterval(a);
$('audio').mediaelementplayer({
audioWidth: '100%'
});
}
}, 0);
【讨论】:
setInterval作为2016的解决方案吗?