Angular.js - как привязать объект к событию dom

0

Я работаю над игрой, использующей angular.js для ui и класса игрового движка.

Из-за конфликтов между классом игрового движка и библиотекой углового материала я должен загрузить игровой движок в порядок после углового.

После инициализации игрового движка он отправляет пользовательское событие dom "clientReady" с двумя объектами, которые мне нужно получить в моих угловых контроллерах.

Итак, на 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" происходит позднее после углового инициализации, а корневой код не существует, когда он запускает контроллер.

Есть ли способ справиться с этим? Мне интересно, могу ли я как-то запустить контроллеры после события dom.

С уважением, Стефан

  • 0
    В вашем контроллере поместите $ watch на $ rootScope ( docs.angularjs.org/api/ng/type/$rootScope.Scope ). Например, $ rootScope. $ Watch ("engine", function () {}, true); Истина есть, потому что двигатель - это объект.
  • 0
    Проблема в том, что двигатель - гигантский объект, и наблюдение за всеми этими свойствами оказывает серьезное влияние на производительность.
Показать ещё 1 комментарий
Теги:
angular-material

2 ответа

1
Лучший ответ

Вы не можете "запустить" контроллер. Вы можете перейти к представлению, и он запустит его контроллер и свяжет область действия контроллера с соответствующим представлением.

Поэтому, если вы хотите, чтобы это событие слушалось всегда, вы должны сделать это в 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 на одном или нескольких ваших представлениях (при условии, что это событие инициализируется только один раз)

Итак, предположим, что ваш домашний/стандартный вид - '/'. Затем в 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');
    });
}
  1. Далее в маршруте '/game' вы можете начать все свои игровые процессы. Это будет работать, потому что isInitialized() возвращает true ТОЛЬКО при clientReady события clientReady. Если 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();
}
  1. Ваш 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  
    }
};
  • 0
    Спасибо! это работает
0

Вы можете использовать $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);
})

Ещё вопросы

Сообщество Overcoder
Наверх
Меню