Angular.js - 如何从 dom 事件绑定对象
Angular.js - how to bind object from dom event
我正在开发一款使用 angular.js 作为 ui 和游戏引擎 class 的游戏。
由于游戏引擎class和angular-material库之间的冲突,我必须在angular之后按顺序加载游戏引擎。
游戏引擎初始化后,它会发送一个自定义 dom 事件 "clientReady",附加了 2 个我需要在我的 angular 控制器中访问的对象。
所以 app.run 我将这 2 个对象初始化为根范围,如下所示:
app.run(function($rootScope) {
$rootScope.engine = {};
$rootScope.editor = {};
document.addEventListener('clientReady', function(e) {
$rootScope.$apply(function() {
$rootScope.engine = e.detail.engine;
$rootScope.editor = e.detail.editor;
});
});
});
现在在我的控制器中,我正在尝试设置如下范围:
$scope.player = $rootScope.engine.player;
这当然行不通,因为 "clientReady" 事件发生在 angular 初始化之后,并且根范围在启动 运行 控制器时不存在。
有办法处理吗?我想知道我是否可以在 dom 事件后以某种方式启动控制器。
问候
斯特凡
您可以使用$broadcast & $on
进行交流。
document.addEventListener('clientReady', function(e) {
var objData = {};
objData.engine = e.detail.engine;
objData.editor = e.detail.editor;
$rootScope.$broadcast('updated-data',{objData : objData});
});
在控制器中,
$scope.$on('updated-data',function(event,eveneData){
console.log(eveneData);
})
你不能"launch"控制器。您可以转到视图,它将 运行 控制器并将控制器的范围与其相应的视图绑定。
所以如果你想让这个事件一直被监听,你应该在 BodyController 中这样做。但是,如果您只想在 某些 视图中收听此事件,您应该只在 app.run
上执行此操作
app.controller('BodyController', function($rootScope) {
$document.addEventListener('clientReady', function(e) {
// Decide based on view when you want to change initialize the game or not
if($location.path == '/login') {
// don't let the user init as he/she is not logged in
} else {
//init
// Store e in a service or $rootScope. I'd pick a service to do this as I wouldn't want to clutter my $rootScope
GameService.save(e);
// Handle transition to the new path
$location.path('/something');
}
});
})
否则,如果您只想在一个或多个视图中收听此内容。
1. 在您的 one/more 个视图上监听 clientReady 事件(假设此事件仅初始化一次)
那么,假设您的 home/default 视图是“/”。然后在 HomeController 中,你这样做:
app.controller('MainCtrl', function($scope, $document) {
$document.addEventListener('clientReady', function(e) {
// Store e in a service or $rootScope. I'd pick a service to do this as I wouldn't want to clutter my $rootScope
GameService.save(e);
// Goto to View/Controller that needs e
$location.path('/something');
});
}
- 接下来,在“/game”路径中,您可以开始所有的游戏进程。这将起作用,因为
isInitialized()
return 只有在触发 clientReady
事件时才为真。 if isInitialized()return false, then the $location will be changed and execution of GameCtrl will stop (because of
return`语句)
app.controller('GameCtrl', function($scope, GameService, $location) {
if(!GameService.isInitialized()) {
$location.path('/home'); // or to any other route you deem fit
// Instead of redirecting, you can handle this gracefully on this view too. But I think that'll take much more effort.
return; //Important so that the controller is not processed any further
}
// This is where the magic happens!
$scope.engine = GameService.getEngine();
$scope.editor = GameService.getEditor();
}
- 您的
GameService
是存储游戏引擎和其他客户端给定对象的地方。
angular.module('myApp').service('GameService', function() {
// AngularJS will instantiate a singleton by calling "new" on this function
this.getEngine = function() {
// Logic
}
this.getEditor = function () {
// Logic
}
this.isInitialized = function () {
// Logic
}
};
我正在开发一款使用 angular.js 作为 ui 和游戏引擎 class 的游戏。
由于游戏引擎class和angular-material库之间的冲突,我必须在angular之后按顺序加载游戏引擎。
游戏引擎初始化后,它会发送一个自定义 dom 事件 "clientReady",附加了 2 个我需要在我的 angular 控制器中访问的对象。
所以 app.run 我将这 2 个对象初始化为根范围,如下所示:
app.run(function($rootScope) {
$rootScope.engine = {};
$rootScope.editor = {};
document.addEventListener('clientReady', function(e) {
$rootScope.$apply(function() {
$rootScope.engine = e.detail.engine;
$rootScope.editor = e.detail.editor;
});
});
});
现在在我的控制器中,我正在尝试设置如下范围:
$scope.player = $rootScope.engine.player;
这当然行不通,因为 "clientReady" 事件发生在 angular 初始化之后,并且根范围在启动 运行 控制器时不存在。
有办法处理吗?我想知道我是否可以在 dom 事件后以某种方式启动控制器。
问候 斯特凡
您可以使用$broadcast & $on
进行交流。
document.addEventListener('clientReady', function(e) {
var objData = {};
objData.engine = e.detail.engine;
objData.editor = e.detail.editor;
$rootScope.$broadcast('updated-data',{objData : objData});
});
在控制器中,
$scope.$on('updated-data',function(event,eveneData){
console.log(eveneData);
})
你不能"launch"控制器。您可以转到视图,它将 运行 控制器并将控制器的范围与其相应的视图绑定。
所以如果你想让这个事件一直被监听,你应该在 BodyController 中这样做。但是,如果您只想在 某些 视图中收听此事件,您应该只在 app.run
app.controller('BodyController', function($rootScope) {
$document.addEventListener('clientReady', function(e) {
// Decide based on view when you want to change initialize the game or not
if($location.path == '/login') {
// don't let the user init as he/she is not logged in
} else {
//init
// Store e in a service or $rootScope. I'd pick a service to do this as I wouldn't want to clutter my $rootScope
GameService.save(e);
// Handle transition to the new path
$location.path('/something');
}
});
})
否则,如果您只想在一个或多个视图中收听此内容。 1. 在您的 one/more 个视图上监听 clientReady 事件(假设此事件仅初始化一次)
那么,假设您的 home/default 视图是“/”。然后在 HomeController 中,你这样做:
app.controller('MainCtrl', function($scope, $document) {
$document.addEventListener('clientReady', function(e) {
// Store e in a service or $rootScope. I'd pick a service to do this as I wouldn't want to clutter my $rootScope
GameService.save(e);
// Goto to View/Controller that needs e
$location.path('/something');
});
}
- 接下来,在“/game”路径中,您可以开始所有的游戏进程。这将起作用,因为
isInitialized()
return 只有在触发clientReady
事件时才为真。 if isInitialized()return false, then the $location will be changed and execution of GameCtrl will stop (because of
return`语句)
app.controller('GameCtrl', function($scope, GameService, $location) {
if(!GameService.isInitialized()) {
$location.path('/home'); // or to any other route you deem fit
// Instead of redirecting, you can handle this gracefully on this view too. But I think that'll take much more effort.
return; //Important so that the controller is not processed any further
}
// This is where the magic happens!
$scope.engine = GameService.getEngine();
$scope.editor = GameService.getEditor();
}
- 您的
GameService
是存储游戏引擎和其他客户端给定对象的地方。
angular.module('myApp').service('GameService', function() {
// AngularJS will instantiate a singleton by calling "new" on this function
this.getEngine = function() {
// Logic
}
this.getEditor = function () {
// Logic
}
this.isInitialized = function () {
// Logic
}
};