Angular.js -如何从dom事件绑定对象

Angular.js - how to bind object from dom event

本文关键字:dom 事件 绑定 对象 js Angular      更新时间:2023-09-26

我正在制作一个使用angular.js作为UI和游戏引擎类的游戏。

由于游戏引擎类和angular-material库之间的冲突,我必须在angular之后依次加载游戏引擎。

一旦游戏引擎被初始化,它会调度一个自定义dom事件"clientReady",附带2个对象,我需要在我的angular控制器中访问。

那么在app.run中,我将这两个对象初始化为根作用域,像这样:

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初始化之后,而且当它开始运行控制器时,rootscope还不存在。

有办法处理这个吗?我想知道我是否可以在dom事件之后以某种方式启动控制器。

的问候Stefan

不能"启动"控制器。你可以去到视图,它会运行控制器并将控制器的作用域与它相应的视图绑定。

如果你想让这个事件一直被监听,你应该在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. 在一个/多个视图上监听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"路由中,你可以开始所有的游戏进程。这将起作用,因为只有当clientReady事件被触发时,isInitialized()才返回true。如果isInitialized() return false, then the $location will be changed and execution of GameCtrl will stop (because of返回语句)
  • 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  
        }
    };

    您可以使用$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);
    })