我在程序员的堆栈交换中问了这个问题,但没有得到任何回复,所以我想我在这里试试运气......
我正在开发一个项目,我希望封装一个指令库并将其分发给其他开发人员使用。我想在这个封装的代码中保留对模型的更改,所以我真的不希望开发人员在lib之外更改范围变量。
在我的代码中,我有两种不同的方法可以从父控制器与我的lib进行通信。
第一个理论是创建一个包含指令和服务的lib。父控制器将调用该服务,该服务将处理lib模型的所有更改,并且指令将根据这些更改做出反应。
第二个理论是将所有函数放在指令本身中更改模型,并调用父指令范围来进行更改。
这是一个能够更详细地展示我要求的东西。这是一个简单的例子,但说明了两种不同的方法。
http://plnkr.co/edit/CR350Vx7NiHs5tkjNWZL?p=preview
我倾向于第二种方法,因为从开发场景中实现起来似乎更清晰。
Angular专家的建议是什么?
Plunker Html:
<body ng-app="myApp">
This is Example 1 - Using a service to modify directive
<div ng-controller="Example1Ctrl">
<example1-directive ng-model='example1Model'></example1-directive>
<br>
<br>
<input type="button" value="Change Example 1" ng-click='changeExample1()' />
</div>
<br>
<br>
This is Example 2 - Modifying directive in the scope of the directive
<div ng-controller="Example2Ctrl">
<example2-directive ng-model='example2Model'></example2-directive>
<br>
<br>
<input type="button" value="Change Example 2" ng-click='changeExample2()' />
</div>
</body>
Plunker js
var app = angular.module("myApp", []);
//--------------------------------------------------
//-------- This is example 1
//--------------------------------------------------
app.controller("Example1Ctrl", function($scope, example1Svc) {
$scope.example1Model = {
value: "Example 1 - Original Value"
}
$scope.changeExample1 = function() {
example1Svc.change($scope.example1Model, "Example 1 - Changed Value");
}
});
/// This part would be encapsulated in a lib
app.directive("example1Directive", function() {
return {
restrict: "E",
scope: {
model: "=ngModel"
},
template: "{{model.value}}"
}
});
app.service("example1Svc", function() {
this.change = function(example1Model, newValue) {
example1Model.value = newValue;
}
})
// End lib
//--------------------------------------------------
//-------- This is example 2
//--------------------------------------------------
app.controller("Example2Ctrl", function($scope, example1Svc) {
$scope.example2Model = {
value: "Example 2 - Original Value"
}
$scope.changeExample2 = function() {
$scope.example2Model.change("Example 2 - Changed Value");
}
});
/// This part would be encapsulated in a lib
app.directive("example2Directive", function() {
return {
restrict: "E",
scope: {
model: "=ngModel"
},
template: "{{model.value}}",
controller: function ($scope) {
$scope.model.change = function(newValue) {
$scope.model.value = newValue;
}
}
}
});
// end lib
答案 0 :(得分:2)
我对你的例子#1感到有些困惑。 exampleSvc.change
做了什么?
示例#2肯定违背MVVM最佳实践,因为它将控制器与视图耦合。控制器(视图)应与视图无关。他们应该只更改ViewModel以反映应用程序的当前状态。然后,View将对ViewModel中的更改作出反应(但是View选择)。
特别是,这些行“冒犯”了我心目中的最佳做法:
$scope.model.change = function(newValue) {
$scope.model.value = newValue;
}
现在你的控制器依赖于视图来定义函数的功能(或者它是否定义为开始)。另外,如果另一个指令决定改变.change函数怎么办?
编辑: 看看这个SO question,特别是Mark的回答。
编辑#2:编辑#2: 当一些事件需要达到可能感兴趣的指令或子控制器时,有一个有趣的案例。使用$ scope。$ broadcast(在控制器中)和$ scope。$ on(在指令中)来处理。这是一个plunker答案 1 :(得分:1)
我将同意@New Dev并添加更多想法。如果您正在构建一个指令库,那么您也不想捆绑库的使用者必须使用的控制器。您的指令应该或多或少地自包含,并提供足够的api以便可扩展并可能在其他指令中使用。
这是什么意思?您的指令可能需要定义一个控制器,以便它们可以注入其他指令。 E.g。
//your library
directiveModule.directive("example1Directive", function() {
return {
controller: function($scope, $element, $attrs) {
...
},
...
}
});
-
//application
app.directive("appDirective", function() {
return {
require: '?example1Directive',
link: function(scope, element, attrs, example1Directive) {
...
}
});
您可能还想指定可在指令上使用参数设置的各种选项,例如
<div example1-directive="{opt1: 'val', opt2: scopeProp}"></div>
然后,您的指令需要解析该属性并在作用域上执行以生成选项。您还可以做更多的事情,我建议您查看ngmodules.org,看看其他人在做什么。