zoukankan      html  css  js  c++  java
  • AngularJs scope详解

    一.scope是什么?

      scope是表达式(expression)的执行上下文,scope可以监测($watch)表达式(expression)的变化和传播事件($emit,$broadcast).

    二.scope特性

      1.scope提供$watch API,用于监测model的变化

           2.scope提供$apply API,将angular环境外的dom操作应用到angular环境上

           3.scope通过原型,从parent scope继承属性。child scope可以直接访问parent scope上的属性,parent scope没法直接访问child scope上的属性

    三.scope层次结构

      每一个angular应用有且仅有一个root scope,但可以拥有多个child scope。

           应用可以拥有多个child scope,一些directive会创建新的child scope(如ng-repeat)。当新的scope创建后,它们将作为一个child scope添加到parent scope上,这样创建了一个与它们附属的DOM相似的树结构。

          当angular对表达式求值时,它首先查看与当前元素关联的scope的属性。如果没有找到对应的属性,它将会一直向上搜索parent scope,直到到达root scope。在javascript中,这个行为被称为‘原型继承’,child scope 典型继承自它们的parent scope。

    四.scope事件传播

      scope可以类似于DOM事件的方式进行事件传播。事件可以被broadcast到child scope中或者被emit到parent scope中(当前scope有监听也会执行)

      1.parent scope向child scope  broadcast 广播事件和child scope向parent scope emit 分发事件示例:

    <!DOCTYPE html>
    <html>
    <head>
        <title>angular1.x</title>
        <script type="text/javascript" src="../lib/angular1.6.5.js"></script>
    </head>
    <body ng-app="app">    
    
        <div ng-controller="parent">
            {{count}}
            <div ng-click="$broadcast('toChild')">向子元素broadcast事件</div>
            <ul ng-controller="child">
                {{count1}}
                <li ng-click="$emit('toParent')" ng-repeat="item in [1,2,3,4,5,6,7]">{{item}}</li>
                
            </ul>
        </div>
    
    <script type="text/javascript">
        var app = angular.module('app',[]);
        app.controller('parent',['$scope',function($scope){
            $scope.count = 1;
            $scope.$on('toParent',function(){ //child scope $emit向上分发的监听
                $scope.count++;
            });
            $scope.$on('toChild',function(){ //当前scope有监听,也会执行
                $scope.count++;
            })
        }]);
    
        app.controller('child',['$scope',function($scope){
            $scope.count1 = 1;
            $scope.$on('toChild',function(){  //parent scope $broadcast向下广播的监听
                $scope.count1++; 
            })
        }]);
    
    </script>
    </body>
    </html>

      该示例中,点击li 父元素的count会+1;点击‘向子元素broadcast事件’,父count和子的count1也会+1,至于父的count怎么会加1是因为当前scope中有 toChild监听。

    四.scope间的通信 

      1.父scope和子scope之间的通信

         从scope的事件传播小节可以知道,scope.$emit()和scope.$broadcast()可以传递第二个或者更多参数,这些参数将当做对应的监听的回调函数的参数。所以parent scope可以通过$broadcast()的方式向child scope传递数据,child scope可以通过$emit()的方式向parent scope传递数据。那么除了事件传播还有其他的通信方式吗?答案是有。因为scope是类DOM的结构,那么scope也有类dom结构的数据构造。下面来看一下scope的构造。

      

       其中$$childHead即第一个子scope, $$childTail即最后一个子scope, $parent即父scope,$$nextSibling即下一个兄弟scope,$$prevSibling即前一个子scope。

      下面将演示父与子之间的通信:

       html结构如下:

    <div ng-controller="parentCtrl">
            <div ng-controller="firstCtrl"></div>
            <div ng-controller="secondCtrl"></div>
    </div>

      js:

       var app = angular.module('app',[]);
        app.controller('parentCtrl',['$scope',function($scope){
            $scope.title = 'parent';
            console.log($scope.$$childHead.title); // firstChild
            console.log($scope.$$childTail.title); // secondChild
        }]);
    
        app.controller('firstCtrl',['$scope',function($scope){
            $scope.title = 'firstChild';
            console.log($scope.$parent.title); //parent
        }]);
    
        app.controller('secondCtrl',['$scope',function($scope){
            $scope.title = 'secondChild';
        }]);

      2.兄弟scope之间的通信

       从上面的例子可以看到兄弟scope可以通过$scope.$$nextSibling和$scope.$$preSibling进行通信。那么兄弟scope可以通过事件传播进行通信吗?答案是肯定的,不过需要$rootScope作为桥梁。

       还是以这段代码为例:

    <div ng-controller="FirstCtrl"></div>
    <div ng-controller="SecondCtrl"></div>

      

    app.controller("FirstCtrl", [ '$scope', '$rootScope', function($scope, $rootScope){
      $rootScope.$on("pong", function(e, time){
          $scope.time = time;
      });
    
      $scope.ping = function(){
          $rootScope.$broadcast("ping");
      };
    }]);
    app.controller("SecondCtrl", [ '$scope', function($scope){
      $scope.$on("ping", function(e, time){
          $scope.time = time;
      });
      $scope.pong = function(){
          $scope.$emit("pong", new Date());
      };
    }]);

    根据上面这段代码,我们可见,FirstCtrl和SecondCtrl两个兄弟controller,从前者到后者,通信要用$rootScope进行$broadcast(),接收从SecondCtrl的广播,使用$rootScope.$on()即可;而在SecondCtrl中,接收来自FirstCtrl的广播,使用$scope.$on(),发送广播进行通信,使用$scope.$emit(),这才是标准的兄弟controller之间进行广播通信的方式
    angularJS的广播机制一直都因为使用$rootScope导致全局污染以及广播频繁使用导致性能下降而存在争议,我们在设计功能时,尽可能在必需的时候,再使用这种自定义广播 

     五.scope的生命周期

  • 相关阅读:
    使用数据(二)
    lambda表达式
    方法引用::
    开发 Web 应用(一)
    Spring基础(三)
    Spring基础(二)
    Spring 基础(一)
    项目实践之Ajax 技术使用教程
    项目实践之前后端分离详解
    考研计算机基础:构造算法与自上而下逐步完善:实例研究3(嵌套控制结构)
  • 原文地址:https://www.cnblogs.com/erduyang/p/7501354.html
Copyright © 2011-2022 走看看