【问题标题】:Outer AngularJS directive doesn't build inner directive correctly外部 AngularJS 指令没有正确构建内部指令
【发布时间】:2013-12-14 08:18:50
【问题描述】:

使用 AngularJS 1.0.8,我正在尝试创建一些可重用的指令来创建一个 Web 开发人员可以编写具有多个属性的单个“顶级”指令的情况,而该指令又具有包含其他指令的模板,这些指令本身可能包含其他指令等。

我遇到的问题是让“内部”模板了解顶级属性。我认为这将是一个普遍的问题,但从我的研究来看,没有其他人在问这个问题。

我创建了这个Plunker 来显示问题:

<!DOCTYPE html>
<html ng-app="outerInnerDirectivesApp">
<head>
    <title>Outer/Inner Directives</title>
</head>
<body>
<div>Single level directive follows:</div>
<single-level-directive single-level-id="single123"></single-level-directive>
<div>Outer/inner directive follows (Expecting "outer123"):</div>
<outer-directive outer-id="outer123"></outer-directive>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
<script src="app.js"></script>
<script src="directives.js"></script>
</body>
</html> 

在 Plunker 中,

  1. 单级指令有效,而且我认为是显示数据的标准方式。

  2. 外部指令和内部指令不起作用。

我期望这些会发生的是

(i) outerDirective 编译/链接以生成 html

<inner-directive inner-id="outer123"></inner-directive>

然后

(ii) innerDirective 编译/链接以生成 html

<div>outer123</div>

但是在第 (ii) 步我得到了

<inner-directive inner-id="" class="ng-isolate-scope ng-scope">
   <div class="ng-binding"></div>
</inner-directive>

所以innerDirective会生成一个空的div。

其实如果我把outer-template.html改成

<div>{{outerId}}<div>

然后该值正确显示,因此看起来 scope.outerId 在正确的位置可用,但 Angular 对我尝试以我现在的方式使用它并不满意。

期望 Angular 这样做是合理的吗?如果是这样,我错过了什么?如果不是,那么您认为从简单的指令集构建更复杂的屏幕的明智替代方法是什么?

【问题讨论】:

    标签: javascript html angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    如果您要设计具有隔离范围的指令,我建议使用隔离范围来定义您要使用的属性类型:

    outerInnerApp.directive("outerDirective", function() {
      return {
        restrict: "E",
        scope: {
          outerId: '@'
        },
        link: function(scope, element, attrs) {
    
        },
        templateUrl: "outer-template.html"
      };
    });
    outerInnerApp.directive("innerDirective", function() {
      return {
        restrict: "E",
        scope: {
          innerId: '='
        },
        link: function(scope, element, attrs) {
    
        },
        templateUrl: "inner-template.html"
      };
    });
    

    这是working plunker

    您的外部指令正在使用属性中定义的值。因此,要将值传递到隔离范围,我们可以使用@。然后内部作用域通过绑定一个变量。所以,我们可以使用=来设置绑定属性。

    【讨论】:

    • 谢谢,戴文。这正是我所需要的。事实上,你的回答显示了我理解的一个很大的空白,这非常有用!
    • 为了他人的利益,我将在下面解释我的原始知识差距(如果我错了,请纠正我,任何人)。 outerId: '@' 位很好。它正在寻找 HTML 中的属性 ...outer-id="value"... 或 ...outer-id={{interpolatedValue}} 然而,我不喜欢的是 innerId: '='增加了一层间接性。它在 HTML 中查找 ...inner-id='propertyName',然后查找 $parentScope.propertyName 的值以得出实际值。
    【解决方案2】:

    对此有更多想法。更多地使用了 AngularJS,我不确定是否要绑定到范围(使用“=”)。事实上,我可以通过进行以下更改来让原始 Plunkr 工作:

    outerInnerApp.directive("outerDirective", function() {
        return {
            restrict: "E",
            scope: {
            //add outerId here
            outerId: "@"
            },
        link: function(scope, element, attrs) {
            //remove scope assignment here
            //scope.outerId = attrs.outerId;
        },
        templateUrl: "outer-template.html"
        };
    });
    outerInnerApp.directive("innerDirective", function() {
        return {
        restrict: "E",
        scope: {
            //add innerId here
            innerId: "@"
        },
        link: function(scope, element, attrs) {
            //remove scope assignment here
            //scope.innerId = attrs.innerId;
        },
        templateUrl: "inner-template.html"
        };
    });
    

    目前我不明白为什么会有不同,比如说,

    innerId:"@"
    

    并在链接函数中设置作用域的值

    link: function(scope, element, attrs) {
        scope.innerId = attrs.innerId;
    }
    

    当我发现它的行为不同时,我会回复。

    【讨论】:

    • 您可能希望将此作为自己的问题发布,而不是作为对已被回答和接受的问题的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多