我对此帖Pass Angular scope variable to Javascript也有同样的问题。但我无法用他们的答案来解决我的问题。
我的角度控制器
<div class="main">
<div id="logo"><img src="img/logo.png" /></div>
<div id="main-links">
<a style="cursor:pointer"><img id="img-1" style="margin-left: 0" src="img/icons/forums.png" onmouseover="this.src='img/icons/forums-hover.png'" onmouseout="this.src='img/icons/forums.png'" /></a>
<a style="cursor:pointer"><img id="img-2" src="img/icons/servers.png" onmouseover="this.src='img/icons/servers-hover.png'" onmouseout="this.src='img/icons/servers.png'" /></a>
<a style="cursor:pointer"><img id="img-3" src="img/icons/staff.png" onmouseover="this.src='img/icons/staff-hover.png'" onmouseout="this.src='img/icons/staff.png'" /></a>
<a style="cursor:pointer"><img id="img-4" src="img/icons/donate.png" onmouseover="this.src='img/icons/donate-hover.png'" onmouseout="this.src='img/icons/donate.png'" /></a>
</div>
</div>
我的Html
angular.module('App').controller('HomeController', [
'$rootScope', '$scope', '$state', '$timeout', 'ReportService', 'MsgService',
function($rootScope, $scope, $state, $timeout, ReportService, MsgService) {
$scope.$on('$viewContentLoaded', function() {
console.log('HomeController');
$scope.get_locations();
});
// get locations
$scope.get_locations = function() {
var data = {};
// call http get to my api
MsgService.get_all_locations(data, function(response) {
if (response.code == 1) { // success
$scope.locations_array = response.data; // data that I want to access to script
} else {
alert(response.message);
}
});
}
}
]);
我尝试从浏览器开发工具访问然后它可以访问范围。但是我的代码无法访问它。
如何解决这个问题?
答案 0 :(得分:2)
此处的直接问题是计时问题 - 您在填充值之前很久就试图从范围中读取locations_array
值。
事件的顺序如下:
ready
事件,在Angular甚至考虑启动之前,你的内联JS代码会运行,试图从范围中读取值,但目前还不存在。ready
事件(这可能在#1之前,具体取决于页面上脚本的顺序)。这将调用HomeController
构造函数,该构造函数仅为$viewContentLoaded
事件设置一个侦听器。$viewContentLoaded
事件被广播,您发起对位置的异步请求。.scope()
除了时序问题之外,您的解决方案还有另一个主要问题 - 它依赖于AngularJS包含的调试信息。显然,它是默认的,但是disable this debug information可以在生产中获得显着的性能提升。
如果其他人出现,可能在您离开后,并尝试禁用调试信息以提高性能或出于其他原因(这是生产中的推荐做法),它将停止.scope()
从工作。
因此,依靠.scope()
,您正在努力禁用调试信息,这是一种最佳做法和性能助推器,现在或将来都无法用于您的应用,因为它会破坏事物。对于那个开发者而言,这对任何事情来说都是显而易见的。
所以依靠.scope()
进行调试以外的任何事情都应该是最后的选择。
就像我提到的,这是一个计时问题 - 您需要等到最终加载位置,然后再运行依赖它们的代码。
幸运的是,我们在JS中有很多选项来处理异步值 - 回调,承诺,RxJS可观察等等。选择你最喜欢的。
在你的控制器中,在全局范围内创建一个promise(icky,但它需要在某个地方的Angular之外),并在加载时使用位置数据解析该promise。
var resolveLocations;
window.locationsPromise = new Promise(function (resolve) {
resolveLocations = resolve;
});
angular.module('App').controller('HomeController', [
'$rootScope', '$scope', '$state', '$timeout', 'ReportService', 'MsgService',
function($rootScope, $scope, $state, $timeout, ReportService, MsgService) {
$scope.$on('$viewContentLoaded', function() {
console.log('HomeController');
$scope.get_locations();
});
// get locations
$scope.get_locations = function() {
var data = {};
// call http get to my api
MsgService.get_all_locations(data, function(response) {
if (response.code == 1) { // success
resolveLocations(response.data); // resolve the promise
$scope.locations_array = response.data; // data that I want to access to script
} else {
alert(response.message);
}
});
}
}
]);
然后,您的普通(非角度)javascript(需要在加载Angular javascript文件后运行)可以使用该承诺在可用时对数据执行某些操作:
<script type="text/javascript">
$(document).ready(function() {
window.locationsPromise.then(function (locations_array) {
console.dir(locations_array);
// do something with the data
});
});
</script>
在不知道为什么你认为你需要在Angular之外访问这些数据的情况下,很难肯定地说,但是可能还有其他更好的方法来处理Angular代码和依赖于其他Javascript代码之间的相互作用它
也许您创建了一个指令来集成jQuery插件或其他服务,或者其他什么,但由于AngularJS代码只是普通的JS,因此不需要将它们视为彼此独立。您只需要正确的时间,以便获得可用的数据。祝你好运!