AngularJS: 从控制器到指令传递函数的多种方式
AngularJS: Multiple ways to pass function from controller to directive
我正在尝试写组件式AngularJS,类似这个article提出的做法。
但是,我开始意识到有多种方法可以将函数传递给关联控制器的指令。我正在处理的指令非常复杂,我通过绑定到模板中的指令来传递每个函数,但我现在看到我可以隐式继承 $scope
对象或引用 Controller
直接反对。
这是我的意思的一个例子:
app.js
var app = angular.module('plunker', [])
app
.controller('myCtrl', function($scope) {
$scope.output = '';
// fn foo is passed into directive as an argument
$scope.foo = function () {
$scope.output = 'foo';
}
// fn inherited from controller
$scope.bar = function () {
$scope.output = 'bar';
}
// fn attached to ctrl object and referenced directly
this.baz = function () {
$scope.output = 'baz';
}
})
.directive('myDirective', function() {
return {
scope: {
output: '=',
foo: '&',
},
templateUrl: 'template.html',
replace: true,
controller: 'myCtrl',
controllerAs: 'ctrl'
};
})
index.html
<body ng-controller="myCtrl">
<my-directive
output="output"
foo="foo()">
</my-directive>
</body>
template.html
<div>
<button ng-click="foo()">Click Foo</button>
<button ng-click="bar()">Click Bar</button>
<button ng-click="ctrl.baz()">Click Baz</button>
<p>You clicked: <span style="color:red">{{output}}</span></p>
</div>
笨蛋:http://plnkr.co/edit/1JzakaxL3D2L6wpPXz3v?p=preview
所以这里有三个函数,它们都可以工作,只是以不同的方式传递给指令。我的问题是每个的优点是什么,从代码和可测试性的角度来看哪个是最好的?
您实际上并没有向指令传递任何内容,因为它使用 与包含它的文件相同的控制器...
例如,如果您删除以下内容:
scope: {
output: '=',
foo: '&',
}
从你的指令来看,一切仍然有效。我想不出为指令和包含这样的应用程序使用相同控制器的理由。我永远不会推荐这种方法。
如果你也删除
controller: 'myCtrl',
controllerAs: 'ctrl'
只有 foo
和 bar
有效。这是因为该指令继承了它所包含的范围。仅当您的指令非常简单并且与使用它的视图紧密耦合时才建议这样做。当您只是进行一些在页面中重复出现的视觉修改时,通常这种方法是可行的。请注意,当您在控制器中更改某些内容时,指令可能会中断,这违反了封装原则。
最后,将函数传递给指令的正确方法确实是使用 '&'
修饰符。这让你的指令保持一个独立的范围,这意味着如果包含控制器上的某些代码发生变化,它不会中断。这使您的指令真正成为一个封装的独立模块,您可以在任何地方"drag and drop"。
这是一个 fork of your plunkr。
我正在尝试写组件式AngularJS,类似这个article提出的做法。
但是,我开始意识到有多种方法可以将函数传递给关联控制器的指令。我正在处理的指令非常复杂,我通过绑定到模板中的指令来传递每个函数,但我现在看到我可以隐式继承 $scope
对象或引用 Controller
直接反对。
这是我的意思的一个例子:
app.js
var app = angular.module('plunker', [])
app
.controller('myCtrl', function($scope) {
$scope.output = '';
// fn foo is passed into directive as an argument
$scope.foo = function () {
$scope.output = 'foo';
}
// fn inherited from controller
$scope.bar = function () {
$scope.output = 'bar';
}
// fn attached to ctrl object and referenced directly
this.baz = function () {
$scope.output = 'baz';
}
})
.directive('myDirective', function() {
return {
scope: {
output: '=',
foo: '&',
},
templateUrl: 'template.html',
replace: true,
controller: 'myCtrl',
controllerAs: 'ctrl'
};
})
index.html
<body ng-controller="myCtrl">
<my-directive
output="output"
foo="foo()">
</my-directive>
</body>
template.html
<div>
<button ng-click="foo()">Click Foo</button>
<button ng-click="bar()">Click Bar</button>
<button ng-click="ctrl.baz()">Click Baz</button>
<p>You clicked: <span style="color:red">{{output}}</span></p>
</div>
笨蛋:http://plnkr.co/edit/1JzakaxL3D2L6wpPXz3v?p=preview
所以这里有三个函数,它们都可以工作,只是以不同的方式传递给指令。我的问题是每个的优点是什么,从代码和可测试性的角度来看哪个是最好的?
您实际上并没有向指令传递任何内容,因为它使用 与包含它的文件相同的控制器...
例如,如果您删除以下内容:
scope: {
output: '=',
foo: '&',
}
从你的指令来看,一切仍然有效。我想不出为指令和包含这样的应用程序使用相同控制器的理由。我永远不会推荐这种方法。
如果你也删除
controller: 'myCtrl',
controllerAs: 'ctrl'
只有 foo
和 bar
有效。这是因为该指令继承了它所包含的范围。仅当您的指令非常简单并且与使用它的视图紧密耦合时才建议这样做。当您只是进行一些在页面中重复出现的视觉修改时,通常这种方法是可行的。请注意,当您在控制器中更改某些内容时,指令可能会中断,这违反了封装原则。
最后,将函数传递给指令的正确方法确实是使用 '&'
修饰符。这让你的指令保持一个独立的范围,这意味着如果包含控制器上的某些代码发生变化,它不会中断。这使您的指令真正成为一个封装的独立模块,您可以在任何地方"drag and drop"。
这是一个 fork of your plunkr。