• [译]Exploring Angular 1.3: Binding to Directive Controllers


    原文: http://blog.thoughtram.io/angularjs/2015/01/02/exploring-angular-1.3-bindToController.html

    Angular1.2引入了新的语法 controllerAs, 它让scope更加清楚、干净, 让controller更加聪明. 在我们的Angular应用中使用controllerAs可以避免开发者经常遇到的一些问题.

    controllerAs 做为命名空间

    让我们用代码说事,有两个controller如下:

    function ControllerOne($scope) {
      $scope.foo = 'Pascal';
    }
    
    function ControllerTwo($scope) {
      $scope.foo = 'Christoph';
    }
    
    app.controller('ControllerOne', ControllerOne);
    app.controller('ControllerTwo', ControllerTwo);
    

    HTML如下:

    <div ng-controller="ControllerOne">
      {{foo}}
      <div ng-controller="ControllerTwo">
        {{foo}}
      </div>
    </div>

    ControllerTwo中的{{foo}}会覆盖ControllerOne中的 {{foo}}, 第一个{{foo}}会显示'Pascal', 第二个{{foo}}显示'Christoph'.

    如果我们想在ControllerTow中显示'Pascal'可以使用scope的$parent属性去引用父作用域:

    <div ng-controller="ControllerOne">
      {{foo}}
      <div ng-controller="ControllerTwo">
        {{$parent.foo}}
      </div>
    </div>
    

    然而使用$parent不是一个好的解决方案, 因为如果嵌套一多我们的代码就不利于维护了. 想象下如果你有4层或5层嵌套. 你的代码会变成$parent.$parent.$parent.$parent, 这是不是很糟糕?

    首先我们使用this替代$scope:

    function ControllerOne() {
      this.foo = 'Pascal';
    }
    
    function ControllerTwo() {
      this.foo = 'Christoph';
    }
    

    接下来, 我们修改ngController指令,使用controllerAs语法:

    <div ng-controller="ControllerOne as ctrl1">
      {{ctrl1.foo}}
      <div ng-controller="ControllerTwo as ctrl2">
        {{ctrl2.foo}}
      </div>
    </div>
    

    当使用controller的时候,我们就可以使用controllerAs. 例如在Angular的$routeProvider中我们也可以使用controllerAs.

    $routeProvider.when('/', {
      templateUrl: 'stateTemplate.html',
      controllerAs: 'ctrl',
      controller: 'StateController'
    });
    

    指令也可以有controller, 所以我们在定义指令的时候也可以使用controllerAs.

    app.controller('SomeController', function () {
      this.foo = 'bar';
    });
    
    app.directive('someDirective', function () {
      return {
        restrict: 'A',
        controller: 'SomeController',
        controllerAs: 'ctrl',
        template: '{{ctrl.foo}}'
      };
    });

    在指令中使用controllerAs的问题

    我们说过,当使用controllerAs的时候controller的scope绑定到controller的this对象, 也就是说this代表我们的scope. 那么当指令有自己隔离的scope时,它会如何工作呢?

    下面的指令有一个隔离的scope,一个controller和一个使用controller属性的template:

    app.directive('someDirective', function () {
      return {
        scope: {},
        controller: function () {
          this.name = 'Pascal'
        },
        controllerAs: 'ctrl',
        template: '<div>{{ctrl.name}}</div>'
      };
    });
    

    如果这个name要进行双向绑定该怎么做呢?

    app.directive('someDirective', function () {
      return {
        scope: {
          name: '='
        },
        // ...
      };
    });
    

    如果我们在外部修改隔离scope的属性,他不会反应到controller的this对象中去. 在AngularJS1.2中, 当属性变化的时候我们使用$scope服务显示的重新对我们的scope赋值. 不要忘了把$watch的callback绑定到controller的this:

    app.directive('someDirective', function () {
      return {
        scope: {
          name: '='
        },
        controller: function ($scope) {
          this.name = 'Pascal';
    
          $scope.$watch('name', function (newValue) {
            this.name = newValue;
          }.bind(this));
        },
        // ...
      };
    });
    

    等等,开始去掉的$scope 现在又回来了. 而且现在为了进行双向绑定我们额外写了许多代码.

    幸运的是, 这些在AngularJS 1.3中得到了很好的解决!

    使用bindToController绑定controller

    Angular 1.3在指令中引入了一个新的属性bindToController. 当设置bindToController为true时,属性是绑定到controller而不是scope.

    这意味, 当controller实例化, 隔离scope的初始值绑定到this上, 将来对这些属性值的改变也会自动反应.

    app.directive('someDirective', function () {
      return {
        scope: {
          name: '='
        },
        controller: function () {
          this.name = 'Pascal';
        },
        controllerAs: 'ctrl',
        bindToController: true,
        template: '<div>{{ctrl.name}}</div>'
      };
    });
    

    看, 现在不需要$scope了.

    1.4中的改善

    1.4中bindToController更加强大.在1.4中, 我们可以把所有要绑定到隔离scope的属性移到bindToController中.

    下面的例子中. 不再在scope中定义scope属性了:

    app.directive('someDirective', function () {
      return {
        scope: {},
        bindToController: {
          someObject: '=',
          someString: '@',
          someExpr: '&'
        }
        controller: function () {
          this.name = 'Pascal';
        },
        controllerAs: 'ctrl',
        template: '<div>{{ctrl.name}}</div>'
      };
    });
    
  • 相关阅读:
    在WM中画个带有边框的Panel
    在PPC上安装SQL Mobile库
    利用SQL语句清理日志
    Asp.net Ajax 中的脚本错误: Sys未定义的解决方法
    python搭建简易服务器
    STL源码剖析读书笔记第3章
    mongodb 查找 排序 索引 命令
    STL源码剖析读书笔记第2章
    词排序
    关于淘宝直通车优化的一点感悟
  • 原文地址:https://www.cnblogs.com/irocker/p/binding-to-directive-controllers.html
Copyright © 2020-2023  润新知