将 ControllerAs 与指令一起使用

Using ControllerAs with a Directive

我正在尝试遵循 John Papa 的 angularJS 风格指南 here 并开始将我的指令切换为使用 controllerAs。但是,这是行不通的。我的模板似乎无法访问分配给 vm 的任何内容。请参阅展示行为的这个非常简单的 plnkr 示例。

http://plnkr.co/edit/bVl1TcxlZLZ7oPCbk8sk?p=preview

angular
    .module('app', []);

angular
    .module('app')
    .directive('test', test);

function test() {
    return {
        restrict: 'E',
        template: '<button ng-click="click">{{text}}</button>',
        controller: testCtrl,
        controllerAs: 'vm'
    }
}

angular
    .module('app')
    .controller('testCtrl', testCtrl);

function testCtrl() {
  var vm = this;
  vm.text = "TEST";
}

当使用 controllerAs 语法时,您不会像往常一样访问 $scope,变量 vm 被添加到范围中,因此您的按钮需要变为:

<button ng-click="click">{{vm.text}}</button>

注意 vm. 添加到 text 的开头。

Here is a fork of your Plunk with the fix applied


问:您知道我如何访问作为属性传递给指令的属性吗,例如 "scope: { text: '@' }"?然后我是否被迫在控制器上使用 $scope 并设置 vm.text = $scope.text?

答:在您引用的那篇文章中,a section y075 就是谈到了这种情况。查看 bindToController:

return {
    restrict: 'E',
    template: '<button ng-click="click">{{text}}</button>',
    controller: testCtrl,
    controllerAs: 'vm',
    scope: {
        text: '@'
    },
    bindToController: true // because the scope is isolated
};

那么你应该可以访问vm.text

使用 "controllerAs",控制器实例别名 - vm,在你的例子中 - 作为范围的 .vm 属性 在范围上发布。

因此,要访问其属性(即控制器的属性),您需要指定 {{vm.text}}ng-click="vm.click"

当你使用 controllerAs 语法时,你必须使用

bindToController: true

它将在您的指令中起作用。

当使用'controllerAs'语法时,如上所述,范围绑定到控制器的'this'引用。 所以它允许我们引入一个新的命名空间('vm' 在这里)绑定到我们的控制器,而不需要将范围属性放在额外的对象文字中(比如 $scope). 因此访问控制器范围内的任何内容,需要 'vm' 命名空间,如,

'<button ng-click="click">{{vm.text}}</button>'

我知道这张票很旧了。我加了 0.02 美元,以防将来有人无意中发现这个问题。

首先,最好了解一下您要实现的目标的背景信息,因为您似乎违反了设计规则。你的指令不需要知道控制器的内部工作原理,或者 vice-versa.

我创建了一个简单的示例来说明如何在指令中设置按钮的标题。这里不需要控制器,我认为这只会让你的例子难以理解。

var myApp = angular.module('myApp', []);

myApp.directive('myDirective', function() {
  return {
    scope: {
      caption: "@"
    },    
    template: '<button>{{caption}}</button>'
  };
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>

<div ng-app="myApp">
  <my-directive caption="Hello World" />
</div>