![](/img/trans.png)
[英]document.ready alternative for AngularJS outside of AngularJS
[英]$(document).ready alternative for AngularJS
我正在使用一个名为Gentelella的模板,我正在尝试将AngularJS实现到它中。 但是,我遇到了某个Javascript文件的问题。 在此文件的末尾,调用$(document).ready
函数,该函数初始化在HTML代码中进行一些更改的Javascript代码。 问题是在HTML完全加载之前, $(document).ready
函数调用得太早。
出现此问题可能是因为我正在使用ngRoute,这会将模板html文件注入index.html的ng-view。 当发生这种情况时,DOM可能已经在AngularJS注入模板(= HTML)之前宣布准备好文档。
基本上,一旦AngularJS注入模板,我只需要找到一种方法在Javascript文件中调用一些代码。
我附上了一些代码来深入了解这个问题:
custom.min.js的片段
$(document).ready(function () {
init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
});
main.js的片段:
.config(function($routeProvider, $httpProvider) {
$routeProvider.when('/', {
templateUrl : 'dash.html',
controller : 'dash',
controllerAs: 'controller'
}).when('/login', {
templateUrl : 'login.html',
controller : 'navigation',
controllerAs: 'controller'
}).when('/plain_page', {
templateUrl : 'plain_page.html',
controller : 'dash',
controllerAs: 'controller'
}).otherwise('/');
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
})
提前致谢!
许多jQuery插件依赖于1.绘制DOM的工作流程。 2.运行init()
函数来设置针对这些DOM元素的代码。
该工作流在Angular中表现不佳,因为DOM不是静态的:Angular在其自己的生命周期中设置和销毁DOM节点,这可以覆盖在Angular之外进行的事件绑定或DOM更改。 当您使用Angular时,文档就绪并不是特别有用,因为它表明Angular本身已准备好开始运行。
要有效地使用Angular,您必须养成仅在实际需要时才启动代码的习惯。 而不是init_foo(); init_bar();
init_foo(); init_bar();
在document.ready上,你应该有一个带有自己的初始化代码的Foo指令,以及一个带有自己特定初始化代码的Bar指令,依此类推。 这些指令中的每一个都应该只修改由该特定指令创建的DOM。 这是确保您需要修改的DOM元素实际存在的唯一安全方法,并且您不会在指令之间创建冲突或意外的相互依赖性。
举一个例子:我猜你的init_flot_chart()
通过DOM向下搜索,寻找一个特定元素,在其中绘制一个flot图表。 而不是那种自上而下的方法,创建一个指令:
angular.module('yourApp')
.directive('flotWrapper', function () {
return {
template: "<div></div>",
scope: {
data: '@'
},
link: function(scope, elem, attrs) {
var options = {}; // or could pass this in as an attribute if desired
$.plot(elem, scope.data, options); // <-- this calls flot on the directive's element; no DOM crawling necessary
}
};
});
您使用这样的:
<flot-wrapper data="{{theChartData}}"></flot-wrapper>
...其中theChartData
是一个对象,包含要在图表中绘制的任何数据。 (您可以添加其他属性以传入您喜欢的任何其他参数,例如flot选项,标题等)
当Angular绘制flotWrapper指令时,它首先在指令模板中创建DOM元素,然后针对模板的根元素运行其link
函数中的任何内容。 (flot库本身可以通过普通的旧<script>
标签包含在内,因此当指令需要时,它的plot
功能可用。)
(注意,如果theChartData
的内容theChartData
变化,这不会自动更新; 这里可以看到一个更精细的例子,它也会观察变化并做出适当的响应。)
在使用ngRoute
,控制器将在加载页面时运行。 当控制器开始执行您想要的任何操作时,您可以调用init()
方法。
function MyCtrl($scope) {
function init() {
console.log('controller started!');
}
init();
}
作为旁注,这是John Papa Angular指南中推荐的最佳实践。
另一种可能是使用ng-init
指令,例如:
<div ng-controller="MyCtrl" ng-init="myFunction()">...</div>
在最新版本的angular.js中有一个名为$postLink()
的生命周期钩子,在此控制器的元素及其子元素已被链接之后调用。 与post-link函数类似,此挂钩可用于设置DOM事件处理程序并执行直接DOM操作。请查看指南
$document.ready(function() {
$scope.$on('$viewContentLoaded', function() {
$timeout(function() {
init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
})
})
})
更新通知 :sry家伙,这不是一个严格的解决方案,请参阅我写的另一个答案
这与角度消化周期有关,它是关于角度如何在引擎盖下工作,数据绑定等。有很好的教程解释这一点。
要解决您的问题,请使用$timeout
,它将使代码在下一个周期执行:
app.controller('Controller', function ($scope, $timeout) {
$scope.$on('$viewContentLoaded', function(event) {
$timeout(function() {
init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
},0);
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.