当前位置:   article > 正文

AngularJS开发学习笔记:父子作用域之间的通信—$on、 $emit、$broadcast的介绍_$on $broadcast

$on $broadcast

angularJs中的作用域($scope)结构和DOM结构非常相似,也是一个层次分明的树状结构。它有一个根作用域$rootscope(对应angular应用或ng-app),其他作用域是嵌套在根作用域下面的。 


angularJs的$scope之间都遵循js中对象原型继承方式,当子作用域中没有该对象时,默认向上级作用域(父作用域)寻找,直到找到或者到达$rootscope为止,当子作用域有该对象时,使用子作用域中的对象。

注:这里的父作用域包含直接父级和祖先,子作用域包含直接子级和更下层级 


例子如下:

  1. <body ng-app="myApp">
  2.     <div ng-controller="fatherCtrl">
  3.         <input type="text" ng-model="name" ng-change="nameOnChange()">
  4.         <h1>Father: {{name}}!</h1>
  5.         <div ng-controller="sonCtrl">
  6.              <input type="text" ng-model="name" ng-change="nameOnChange()"> 
  7.              <h1>Son: {{name}}</h1>
  8.         </div>
  9.     </div>
  10. </body>


其中fatherCtrl 和 sonCtrl 里都使用了 name,但sonCtrl中并没有定义name。

  1. var app = angular.module ('myApp', []);
  2.     app.controller('fatherCtrl', function ($scope) {
  3.         $scope.name = "father";
  4.         $scope.$watch("name",function () {
  5.             console.log("fatherScope:"+$scope.name)
  6.         })
  7.     });
  8.     app.controller('sonCtrl', function ($scope) {
  9.         $scope.$watch("name",function () {
  10.             console.log("sonScope:"+$scope.name)
  11.         })
  12.     });


这时sonCtrl 直接读取 fatherCtrl 中的 name,改变fatherCtrl中name的值,sonCtrl显示的值也会同步改变。

效果如图:


但当通过view同步改变sonCtrl中name的值时,sonCtrl中会重新创建一个name的对象,faterCtrl中的值不会改变。 


效果如图:

è¿éåå¾çæè¿°

如何在作用域之间通信呢? 
1.创建一个单例服务,然后通过这个服务处理所有子作用域的通信。 
2.通过作用域中的事件处理通信。但是这种方法有一些限制;你并不能广泛的将事件传播到所有监控的作用域中。你必须选择是与父级作用域或者子作用域通信。 


$on、$emit和$broadcast使得event、data在controller之间的传递变的简单。 


1、$emit:子传父,传递event与data;

$scope.$emit('name', 'args');


2、$broadcast:父传子,传递event与data;

$scope.$broadcast('name', 'args');


3、$on:监听或接收数据,用于接收event与data;

$scope.$on('name', function(event,data){});


$broadcast、$emit事件必须依靠其他事件(ng-click等)进行触发。

值得注意的是:以上事件的主语是 $scope, 因为所有的事件其实都是作用在scope上的。 


在$on的方法中的event事件参数,其对象的属性和方法如下:

事件属性/方法功能性说明
event.targetScope获取传播事件的作用域
event.currentScope获取接收事件的作用域
event.name 传播的事件的名称
event.stopPropagation() 阻止事件进行冒泡传播,仅在$emit事件中有效
event.preventDefault()  阻止默认事件的发生
event.defaultPrevented如果调用了preventDefault事件则返回true

    


    
    
   
   
 
    

 

 

事件传播的方向如下图:

è¿éåå¾çæè¿°


1、$emit 
该服务贯穿作用域发出一个向上的事件,该事件的生命周期开始于emit被启动的地方,事件一直朝着根作用域传递,传递期间会通知那些注册在作用域上的监听器,在这期间,作用域中的监听器接收到通知,获取事件,但是不会注销事件,事件继续往下传播。 

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>Title</title>
  6.     <script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
  7. </head>
  8. <body ng-app="myApp">
  9. <div ng-controller="fatherCtrl">
  10.     <!--fatherCtrl可以得到-->
  11.     <input type="text" ng-model="name" ng-change="nameOnChange()">
  12.     <h1>Father: {{name}}!</h1>
  13.     <div ng-controller="sonCtrl">
  14.         <!--sonCtrl可以得到-->
  15.         <input type="text" ng-model="name" ng-change="nameOnChange()">
  16.         <h1>Son: {{name}}</h1>
  17.         <div ng-controller="innerCtrl">
  18.             <input type="text" ng-model="name" ng-change="nameOnChange()">
  19.             <h1>inner: {{name}}</h1>
  20.         </div>
  21.     </div>
  22.     <div ng-controller="broCtrl">
  23.         <!--broCtrl得不到-->
  24.         <input type="text" ng-model="name" ng-change="nameOnChange()">
  25.         <h1>brother: {{name}}</h1>
  26.     </div>
  27. </div>
  28. <script>
  29.     var app = angular.module('myApp', []);
  30.     app.controller('fatherCtrl', function ($scope) {
  31.         $scope.name = "father";
  32.         $scope.$on('test', function (e, newName) {
  33.             $scope.name = newName;
  34.         });
  35.     });
  36.     app.controller('sonCtrl', function ($scope) {
  37.         $scope.name = "son";
  38.         $scope.$on('test', function (e, newName) {
  39.             $scope.name = newName;
  40.         });
  41.     });
  42.     app.controller('broCtrl', function ($scope) {
  43.         $scope.name = "brother";
  44.         $scope.$on('test', function (e, newName) {
  45.             $scope.name = newName;
  46.         });
  47.     });
  48.     app.controller('innerCtrl', function ($scope) {
  49.         $scope.name = "inner";
  50.         $scope.nameOnChange = function () {
  51.             $scope.$emit('test', $scope.name);
  52.         }
  53.     });
  54. </script>
  55. </body>
  56. </html>

效果如下:

è¿éåå¾çæè¿°

 

2、$broadcast 
该服务发布一个向下的事件给作用域中的所有子节点,该事件的生命周期也是从broadcast被启动开始。下面的所有子作用域都会接收到通知。之后,事件向下传播,在这期间,作用域中的监听器接收到通知,获取事件,但是不会注销事件,事件继续往下传播。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
  7. </head>
  8. <body ng-app="myApp">
  9. <div ng-controller="fatherCtrl">
  10. <!--fatherCtrl得不到-->
  11. <input type="text" ng-model="name" ng-change="nameOnChange()">
  12. <h1>Father: {{name}}!</h1>
  13. <div ng-controller="sonCtrl">
  14. <input type="text" ng-model="name" ng-change="nameOnChange()">
  15. <h1>Son: {{name}}</h1>
  16. <div ng-controller="outCtrl">
  17. <!--outCtrl可以得到-->
  18. <input type="text" ng-model="name" ng-change="nameOnChange()">
  19. <h1>out in son: {{name}}</h1>
  20. <div ng-controller="innerCtrl">
  21. <!--innerCtrl可以得到-->
  22. <input type="text" ng-model="name" ng-change="nameOnChange()">
  23. <h1>inner in out: {{name}}</h1>
  24. </div>
  25. </div>
  26. </div>
  27. <div ng-controller="broCtrl">
  28. <!--broCtrl得不到-->
  29. <input type="text" ng-model="name" ng-change="nameOnChange()">
  30. <h1>brother: {{name}}</h1>
  31. </div>
  32. </div>
  33. <script>
  34. var app = angular.module('myApp', []);
  35. app.controller('fatherCtrl', function ($scope) {
  36. $scope.name = "father";
  37. $scope.$on('test', function (e, newName) {
  38. $scope.name = newName;
  39. });
  40. });
  41. app.controller('sonCtrl', function ($scope) {
  42. $scope.name = "son";
  43. $scope.nameOnChange = function () {
  44. $scope.$broadcast('test', $scope.name);
  45. }
  46. });
  47. app.controller('broCtrl', function ($scope) {
  48. $scope.name = "brother";
  49. $scope.$on('test', function (e, newName) {
  50. $scope.name = newName;
  51. });
  52. });
  53. app.controller('innerCtrl', function ($scope) {
  54. $scope.name = "inner";
  55. $scope.$on('test', function (e, newName) {
  56. $scope.name = newName;
  57. });
  58. });
  59. app.controller('outCtrl', function ($scope) {
  60. $scope.name = "out";
  61. $scope.$on('test', function (e, newName) {
  62. $scope.name = newName;
  63. });
  64. });
  65. </script>
  66. </body>
  67. </html>

 

效果如图:

è¿éåå¾çæè¿°

 

3、$on 
该服务监听指定类型的事件,获取从emit或者broadcast发布的事件。 


注: 
1、如果在作用域中没有父子关系存在,可以在控制器中注入$rootScope、使用$broadcast服务向下传播事件(但这个慎用),但是不能通过$emit向上传播事件。

2、在作用域中存在父子关系时,可以也仅可以由子控制器使用$emit服务向上传播事件,同时父作用域中的控制监听器可以注销事件。
————————————————
版权声明:本文为CSDN博主「冰雪_318」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lhj20084720208/article/details/78997015

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/222823
推荐阅读
相关标签
  

闽ICP备14008679号