在 Angular 中结合隔离范围访问父控制器数据

Accessing parent controller data in combination with isolated scope in Angular

先是代码,再是解释:

index.html

<!DOCTYPE html>
<html>

<head>
<script data-require="angular.js@*" data-semver="1.3.7" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="app.js"></script>
</head>

<body ng-app="myApp">
<div ng-controller="myCtrl">
    <my-directive data="1" />
    <my-directive data="2" />
</div>
</body>

</html>

app.js

angular.module("myApp", []).directive("myDirective", function ($parent) {
  return {
      restrict: "E",
      scope: {
          data: "@",
      },
      template: function(element, attrs){
        switch(attrs.data){
          case '1':
            return '<h3>'+ $parent.stringForDirective1 + '</h3>';
          case '2':
            return '<h3>'+ $parent.stringForDirective2 + '</h3>';
        }
      }
  };
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});

现在进行说明。如果我要在我的指令上设置 'scope: false',我可以轻松访问控制器的数据,因为指令位于其范围内。但是,根据我的理解,为了将 HTML 属性中的任何值与自定义指令一起使用,必须将整个指令放入一个独立的范围内。

我想将 HTML 属性用于 return 使用父控制器数据的模板。

在使用 'scope: false' 的同时能够传入自定义 HTML 属性时,如何获得控制器数据的好处?

$parent 示例不起作用,我只是添加它来展示我一直在思考解决方案的方式,我认为它清楚地表明了我的意图。

指令可以具有三种可能的作用域模式:

  1. 隔离范围(范围:{})
  2. 子范围(范围:true)
  3. 继承范围(范围:false)

根据指令的需要,这些范围模式中的任何一种都有效。

如果你想创建一个具有隔离范围的指令,那么你可以通过元素的属性将模型传递到你的指令的隔离范围:

scope: {
    modelA: '=', // model binding
    modelB: '@', // string binding
    modelC: '&'  // method binding in parent scope
}

属性

<div directive model-a="user" model-b="hello {{ user.name }}" model-c="addUser(user)"></div>

示例(不是理想的指令实现,但用于展示如何通过属性将模型传递到隔离范围)

angular.module("myApp", []).directive("myDirective", function ($parent) {
  return {
      restrict: "E",
      scope: {
          data: "@",
          stringForDirective1: '=?',
          stringForDirective2: '=?'
      },
      template: '<h3 ng-if="data = '1'">{{stringForDirective1 }}</h3><h3 ng-if="data = '2'">{{stringForDirective2 }}</h3>'

  };
}).controller('myCtrl',function($scope){
$scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
$scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
});

HTML

<body ng-app="myApp">
<div ng-controller="myCtrl">
    <my-directive data="1" string-for-directive1="stringForDirective1" />
    <my-directive data="2" string-for-directive2="stringForDirective2" />
</div>
</body>

不确定为什么要注入 $parent 依赖项。我希望那是你用来展示你的想法的那个:The $parent example does not work, I simply added it to show the way I've been thinking towards a solution, and I think it shows my intent clearly.


无论如何,你不需要这些。要使其全部正常工作,只需摆脱该依赖性,不要将父作用域值连接到模板中,而是让 Angular 在编译模板后处理它(使用双花括号进行绑定) :

switch(attrs.data){
      case '1':
        return '<h3>{{$parent.stringForDirective1}}</h3>';
      case '2':
        return '<h3>{{$parent.stringForDirective2}}</h3>';
    }

那仍然会寻找 scope.$parent,这正是您想要的。

在此处查看完整的工作示例http://plnkr.co/edit/pW5G2Yy4SelW5DxKBMqW?p=preview

或此处,作为片段

angular.module("myApp", [])
  .directive("myDirective", function() {
    return {
      restrict: "E",
      scope: {
        data: "@",
      },
      template: function(element, attrs) {
        switch (attrs.data) {
          case '1':
            return '<h3>{{$parent.stringForDirective1}}</h3>';
          case '2':
            return '<h3>{{$parent.stringForDirective2}}</h3>';
        }
      }
    };
  })
  .controller('myCtrl', function($scope) {
    $scope.stringForDirective1 = 'I was returned by the directive with HTML attribute data having the value 1.'
    $scope.stringForDirective2 = 'I was returned by the directive with HTML attribute data having the value 2.'
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="myApp">
  <div ng-controller="myCtrl">
    <my-directive data="1"></my-directive>
    <my-directive data="2"></my-directive>
  </div>
</body>


注意:必须指定指令结束标记,因为 shorthand 版本只读取第一个指令(Plunker 说你的指令元素上不允许尾随斜线),请参见此处:http://plnkr.co/edit/Qt0z0poU0ogoQq4C9a3n?p=preview