隔离范围视图绑定

时间:2015-05-20 23:27:57

标签: javascript angularjs directive

我一直在使用隔离范围指令一段时间,并且想到了一个问题,看着它的行为:

为什么我不能将我在指令继承范围内定义的变量直接绑定到视图?

让我举一个关于此代码笔的示例: http://codepen.io/anon/pen/VLKjrv

当我在指令控制器中创建一个新的$ scope变量并尝试将其绑定在视图上时,它不起作用。 另一方面,当我将该变量绑定到来自模板指令属性的html时,它确实有效。

查看代码:

<body ng-app="isolated-test-app">
<section ng-controller="isolatedTestCtrl">
    <article>
      <h1>test1</h1>
        <div isolated-directive binding-from-attr="test">
            <span ng-bind="test"></span>
            <span ng-bind="test2"></span>
        </div>
      <h1>test2</h1>
        <div isolated-directive-number-two binding-from-attr="test">
        </div>

    </article>
</section>

angular.module('isolated-test-app', [])

.controller('isolatedTestCtrl', function isolatedTestCtrl($scope){
    $scope.test = 'Binded from parent controller';
})

.directive('isolatedDirective', function isolatedDirective(){

    var directive = {
        scope: {
          bindingFromAttr: '=',
        },
        controller: function directiveController($scope){
           $scope.test2 = 'Binded from directive controller!';
        },
    };

    return directive;
})

.directive('isolatedDirectiveNumberTwo', function isolatedDirective2(){

    var directive = {
        scope: {
          bindingFromAttr: '=',
        },
        template:'<span ng-bind="bindingFromAttr"></span>\
                  <span ng-bind="test2"></span>',
        controller: function directiveController($scope){
           $scope.test2 = 'Binded from directive controller!';
        },
    };

    return directive;
})
  

TEST1

     

从父控制器挂载

     

TEST2

     

从父控制器挂载

     

来自指令控制器!

我期待test1上test2的结果。

为什么会这样?

3 个答案:

答案 0 :(得分:6)

指令模板指令的元素内容在适用范围方面存在差异。

隔离范围scope: {})指令中,隔离范围适用于模板,但不适用于内容。内容与指令的父级具有相同的范围。另请注意,如果定义了模板,则内容将被模板替换。要使用模板之外的内容,需要“转录”(transclude: true)(但这不属于此答案的范围)。

如果您感到困惑,可以随时查看$scope.$id以查看适用的范围:

<div>parent scope: {{$id}} (will be 2)</div>

<isolate-scope>
   contents of isolate scope directive: {{$id}} (will also be 2)
</isolate-scope>

<isolate-scope-with-template>
   contents will be replaced with the template
</isolate-scope-with-template>
.directive("isolateScopeWithTemplate", function(){
   return {
     scope: {},
     template: "template: {{$id}} (will NOT be 2)"
   }
})

(当然,实际$id可能不同)

子范围scope: true)指令中,适用于内容的范围实际上与应用于模板的范围相同(此处相同 - 模板将替换内容如果它存在,除非你转录)。

现在,回答您的问题

第一个<span ng-bind="test2"></span>绑定到父作用域中不存在的$scope.test2,因此它是空的。

<span ng-bind="test2"></span>模板中的isolatedDirectiveNumberTwo绑定到该指令的隔离范围,该指令定义$scope.test2 = 'Binded from directive controller!'

答案 1 :(得分:0)

这是我对http://codepen.io/anon/pen/MwjjBw

中的实验的猜测

因此对于测试1,指令范围没有test / test2,因为dom对象属于控制器。因此,为了更新它,你必须使用

$scope.$parent.test2 = "" ; 

并且对于测试2,因为模板是作为指令的一部分创建的,因此dom对象属于指令并且也可以由控制器访问(我猜$ compile将其添加到控制器范围/监视中)。

您还可以看到test1没有任何观察者,因为没有绑定发生。

答案 2 :(得分:0)

现在我全面了解,正如New Dev的回答在他的回答中所述

  

在隔离范围(范围:{})指令中,隔离范围适用于模板,但不适用于内容。内容与指令的父级具有相同的范围。

所以我了解到指令内容和模板之间存在差异,以及如何在隔离的作用域上继承作用域。 对于我的应用程序,将范围设置为true完全解决了我的问题。

此外,kwan245的解决方案是解决这个问题的真正好办法。

这两个答案都清除了我的想法,非常感谢New Dev和kwan245:)