其中之一是更多" Angular"与指令沟通的方式?

时间:2014-09-24 14:08:25

标签: angularjs angularjs-directive

我在程序员的堆栈交换中问了这个问题,但没有得到任何回复,所以我想我在这里试试运气......

我正在开发一个项目,我希望封装一个指令库并将其分发给其他开发人员使用。我想在这个封装的代码中保留对模型的更改,所以我真的不希望开发人员在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

2 个答案:

答案 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,看看其他人在做什么。