Angular 1.2和1.1之间的指令与模板和没有模板的范围之间的差异?

时间:2014-01-05 12:32:38

标签: angularjs

我是Angular的新手,并试图理解高级指令API - 我想使用指令元素属性在编译函数中重新创建指令模板。 但是当我没有模板集(或模板是空字符串)而不是访问隔离指令范围时,我访问父(控制器)范围。此外 - 这适用于Angular 1.1但不适用于1.2

这是HTML:

<div class="container" ng-app="app" ng-controller="AppController">
      <sandbox title="Attribute Title"></sandbox>
</div>

JavaScript的:

var app = angular.module('app', [], function () {});

app.controller('AppController', function ($scope) {
    $scope.title = "AppController title";
});

app.directive('sandbox', function ($log, $compile) {
    return {
        restrict: 'E',
        scope: {
            title: "@"
        },
        controller: function ($scope, $element, $attrs) {
            $scope.title = "Directive Controller title";
        },
        template: '<h1>Template</h1>', // change it to: '' and Run, than change Angular to 1.2.x
        compile: function (tElement, tAttrs) {
            tElement.append('<h2> Title = {{ title }}</h2>');
        }
    }

});

当你运行它时,你得到:

模板

标题=属性标题

但是当你将模板更改为空字符串时,你会得到Angular 1.2:

标题= AppController标题

使用Angular 1.1.1:

标题=属性标题

我的问题:

为什么设置模板时访问范围与未设置模板时存在差异?

为什么Angular 1.1和1.2之间存在差异(bug? - 没有'template'的指令,isoleted范围接受控制器范围而非指令范围)?

如何在编译函数中构建访问Angular 1.2中隔离范围而非父范围的模板?

为什么指令控制器功能不会使用$ scope.title =“...”更改'title' - 但是在'link'函数'title'中调试'scope'参数时,'title'值为'Directive Controler Title'但它内部(在哪里寻找它)绑定isoleted范围'属性值'?

这是JSFiddle:http://jsfiddle.net/yoorek/zQ66L/4/

1 个答案:

答案 0 :(得分:7)

你已经遇到了1.2中发生的重大变化(以及使用“@”的怪癖)。

1)当你的模板是``Angular时,看不到要应用隔离范围的模板。这是1.2问题的原因在于你的第二个问题的答案。

2)这是1.2破坏性更改的结果 - make isolate scope truly isolate

  

隔离范围现在仅适用于请求它的isolate指令及其模板。

因此,如果没有模板,您将附加到隔离范围之外的元素 来自https://github.com/angular/angular.js/issues/4889

  

因为我们无法区分最初在html文件中的标记   和编译函数中添加的标记也是后者   没有得到隔离范围。

  

...编译函数中的附加标记应该替换为using   模板属性。
  这个想法是模板属性也可以是一个函数。如果它   是一个,它将获取编译元素和编译属性   参数。

3)如上所述,Angular(1.2之后)实际上是在尝试推动您使用模板而不是编译功能。您最好的选择可能是以您使用编译的方式使用模板功能。或者,您可以使用带有$compile的链接函数 - 但这可能会增加不必要的复杂性。

通过在编译函数中附加,你实际上只是添加到模板中,所以它可以解决这个问题。

4)这与@的工作方式有关。来自Angulars guide to scopes

  

在链接中使用attrs。$ observe('attr_name',function(value){...}   函数获取隔离范围属性的插值   使用'@'表示法。例如,如果我们在链接中有这个   function - attrs。$ observe('interpolated',function(value){...} -   value将设置为11.(scope.interpolatedProp未定义   连接功能。相比之下,scope.twowayBindingProp定义于   链接函数,因为它使用'='表示法。)

您可能还会阅读此SO post on the difference between @ and =