AngularJS使用$on、$emit和$broadcast在作用域之间进行交互

lizean 2014-08-31

        AngularJS中的作用域具有继承性,并且结构是嵌套的。也就是说,对于每个Angular应用或者ng-app来说,只有一个主作用域$rootScope,其他所有作用域都会继承这个主作用域,或者嵌套在这个主作用域内部。通常情况下,你会发现作用域之间不会共享变量,并且互相之间不会基于原型继承。

        如果需要在两个作用域之间进行通信,应该怎么做呢?其中一种方法是:创建一个服务,这个服务在整个应用范围内是一个单例,并且所有作用域之间的交互都通过它进行。另一种方法是:通过作用域上的事件进行交互。但是,这样做存在一些局限性。例如,你通常不能向正在监听的所有作用域同时广播事件。你必须选择是和父节点交互还是和子节点交互。

        下面是一个如何监听事件的例子,在例子中,Start System(星系)中的作用域对象正在等待并监听planetDestroyed事件。

scope.$on('planetDestoryed', function(event, galaxy, planet) {
     //自定义事件,这样星球就被摧毁了
     scope.alertnearbyPlanets(galaxy, planet);
});

        事件监听器上的这些额外参数是从哪来的呢?我们来看一看,单个的星球是如何和它所属的Star System进行交互的:

scope.$emit('planetDestroyed', scope.myGalaxy, scope.myPlanet);

        传递给$emit的附加参数将会被当作函数参数传递给监听器函数。同时,$emit只会从当前的作用域向上进行通信,所以星球上可怜的居民(如果他们自已带有作用域对象的话)不会意识到他们的星球正在被摧毁。

        类似地,如果Galaxy(银河系)需要向下和它的子节点进行交互,那么在Star System作用域中,它应该像下面这样进行交互:

scope.$emit('selfDestructSystem', targetSystem);

        然后正在监听此事件的整个Star Systems都需要检查targetSystem,并且决定它们自已是否需要根据所接收的指令进行自我毁灭操作:

scope.$on('selfDestructSystem', function(event, targetSystem) {
     if(scope.mySystem == targetSystem) {
           scope.selfDestruct();  //引爆!!
     }
});

        当然,在事件向上(或者向下)传播的路径上,有一种操作可能是非常必要的,那就是在特定的层级或者作用域上说:“够了,不允许你通过这里!”,或者其他可以阻止事件的默认行为。传递给监听器的事件对象上带有一些函数,它们可以实现以上需求,甚至可以支持更多操作。如下所示:

AngularJS使用$on、$emit和$broadcast在作用域之间进行交互

相关推荐