我正在使用名为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';
})
提前致谢!
答案 0 :(得分:4)
许多jQuery插件依赖于1.绘制DOM的工作流程。 2.运行init()
函数来设置针对这些DOM元素的代码。
该工作流在Angular中表现不佳,因为DOM不是静态的:Angular在其自己的生命周期中设置并销毁DOM节点,这可以覆盖在Angular之外进行的事件绑定或DOM更改。当您使用Angular时,文档就绪并不是特别有用,因为它表明Angular本身已准备好开始运行。
要有效地使用Angular,你必须养成只在实际需要时启动代码的习惯。因此,在document.ready上不是一大堆init_foo(); init_bar();
,而是应该有一个带有自己的初始化代码的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
的内容发生变化,则不会自动更新;可以看到一个更精细的示例,该示例还会监视变化并做出适当的响应{。{3}}。
答案 1 :(得分:1)
当您使用ngRoute
时,您的控制器将在加载页面时运行。
当控制器开始做你想做的任何事情时,你可以调用init()
方法。
function MyCtrl($scope) {
function init() {
console.log('controller started!');
}
init();
}
作为旁注,这是John Papa Angular's guide中推荐的最佳做法。
另一种可能是使用ng-init
指令,例如:
<div ng-controller="MyCtrl" ng-init="myFunction()">...</div>
答案 2 :(得分:0)
在最新版本的angular.js中有一个名为$postLink()
的生命周期钩子,在此控制器的元素之后调用,并且它的子元素已被链接。与post-link函数类似,此挂钩可用于设置DOM事件处理程序并执行直接DOM操作。检查guide
答案 3 :(得分:-1)
$document.ready(function() {
$scope.$on('$viewContentLoaded', function() {
$timeout(function() {
init_sparklines(), init_flot_chart(), init_sidebar(), init_wysiwyg(), init_InputMask(), ...
})
})
})
更新注意:sry家伙,这是不是一个严谨的解决方案,请参阅another answer我写的
答案 4 :(得分:-1)
这与角度消化周期有关,它是关于角度如何在引擎盖下工作,数据绑定等。有很好的教程解释这个。
要解决您的问题,请使用table(all.pos)
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 1 1 2 3 3 2 3 3 3 3 2 2 1 1 1
,它将使代码在下一个周期执行:
$timeout