【问题标题】:[Angular]What is happening when we take two controllerAs reference as "vm"?[Angular]当我们将两个控制器作为引用作为“vm”时会发生什么?
【发布时间】:2017-06-28 20:25:33
【问题描述】:

我试图了解下面代码中到底发生了什么。

我采用了两个名为 widget 和 filter 的指令(我们可以说是兄弟姐妹)。

对于这两者,我将 controllerAs 引用为“vm”,然后它不起作用。

  • 这意味着只有一个 controllerAs 引用暴露给 DOM (这里小部件控制器作为参考暴露。我不知道为什么?)

如果我将其中任何一个控制器更改为对其他内容的引用,那么它可以正常工作。

  • 两个 controllerAs 引用都向 DOM 公开以获得预期结果。

你能用角度解释一下这个功能吗? 当我们为指令提供相同的控制器作为参考时,角度如何评估(这里是兄弟姐妹)。

如果有歧义? 由于每个控制器都有自己的范围,那么它会如何模棱两可?

Here you can see the issue.

这是我的指令结构。

    <div ng-app="myApp">
      {{tt.name}}
      <body-dir>
        <icon-dir>
          <filter-dir>

          </filter-dir>
        </icon-dir>

        <widget-dir>

        </widget-dir>
      </body-dir>
</div>

JS:

var myApp = angular.module('myApp', []);
myApp.controller('filterController', function filterController($scope) {
  var vm = this;
  vm.test = "From filter controller";
  alert("filter");
});
myApp.controller('widgetController', ['$scope', function widgetController($scope) {
  var vm = this;
  vm.widget = "From widget controller";
  alert("widget");
}])
myApp.directive('bodyDir', function() {
  return {
    restrict: 'E',
    link: function($scope) {
      alert('body-dir');
    }
  };
});

myApp.directive('widgetDir', function() {
  return {
    restrict: 'E',
    controller: 'widgetController',
    controllerAs: 'vm',
    template: "<span>{{vm.widget}}</span>",
    link: function($scope) {
      alert('widget-dir');
    }
  };

});
myApp.directive('filterDir', function() {
  return {
    controller: 'filterController',
    controllerAs: 'vm', // If I change something else it's working fine
    restrict: 'E',
    template: "<span>{{vm.test}}</span>",
    link: function($scope) {

      alert('filter-dir');
    }
  };
});
myApp.directive('iconDir', function() {
  return {
    restrict: 'E',
    link: function($scope) {
      alert('icon-dir');
    }
  };

});

【问题讨论】:

  • 你应该隔离至少一个(2个指令中的)范围,通过添加返回的对象范围:{}或范围:{/*你想要的内部(指令)从父控制器访问的范围 */ }
  • 我尝试为 body 指令启用隔离范围,但这并没有解决问题
  • 我的意思是兄弟姐妹指令:)

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

您的指令都没有定义自己的范围,因此它们都使用外部范围(即此处的根范围),并且都尝试将它们的控制器分配给该范围的属性vm。所以最后一个赢了。

基本上,您的模板代码会导致以下情况发生:

$rootScope.vm = filterController;
$rootscope.vm = widgetController;

【讨论】:

  • 如果指令中没有作用域,它应该采用父作用域对吗?这里是 body 指令范围。为什么它在 rootscope 下?
  • 我尝试为 body 指令启用隔离范围。但还是这样
  • body 指令也没有自己的作用域,所以它也使用了rootScope。为 body 定义一个隔离作用域不会有太大变化:现在两个指令都将尝试使用自己的控制器初始化 body 的 scope.vm。
【解决方案2】:

您应该通过添加返回的对象来隔离至少一个(2 个指令中的一个)范围,以使您的代码正常工作

    scope : { } or 
    scope : { 
       /* pass here what you'd like the inner (directive) scope 
          to access from the parent controller */ 
         }


    myApp.directive('widgetDir', function() {
     return {
       restrict: 'E',
       controller: 'widgetController',
       controllerAs: 'vm',
       template: "<span>{{vm.widget}}</span>",
       scope : {

       },

       link: function($scope) {
         alert('widget-dir');
       }
   };

 });

【讨论】:

  • 我知道它是这样工作的。但我想知道为什么我提到的方式行不通
  • jsfiddle.net/ADukg/12212 实际上完全不使用控制器别名,所有代码都可以正常工作,我认为通过为控制器提供别名,我们会覆盖 Angular 在这种情况下跟踪范围的方式 :)
  • 这很好,但为了获得最佳实践,我们应该使用这个参考,对吗?
  • jsfiddle.net/ADukg/12226 我更改了您的代码以说明 Angular 赋予 $scope 对象的属性。打开控制台,看到 vm 只是 filter 指令作用域上的一个属性,所以通过给一个别名,我们将实际作用域缩小到我猜的 vm
【解决方案3】:

如果您希望兄弟指令具有不同的继承范围,请使用scope: true

    <icon-dir>
    </icon-dir>

    <widget-dir>
    </widget-dir>
myApp.directive('widgetDir', function() {
  return {
    restrict: 'E',
    //DECLARE inherited scope
    scope: true,
    controller: 'widgetController',
    controllerAs: 'vm',
    template: "<span>{{vm.widget}}</span>",
    link: function($scope) {
      alert('widget-dir');
    }
  };

});
myApp.directive('filterDir', function() {
  return {
    restrict: 'E',
    //DECLARE inherited scope
    scope: true,
    controller: 'filterController',
    controllerAs: 'vm', // If I change something else it's working fine
    template: "<span>{{vm.test}}</span>",
    link: function($scope) {

      alert('filter-dir');
    }
  };
});

继承的子作用域 (scope:true) 将在每个兄弟的不同作用域上拥有控制器的 vm 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多