AngularJS - 带有ng-transclude的指令,没有双向绑定

时间:2015-02-13 16:03:48

标签: angularjs angularjs-ng-transclude

查看DEMO

<body ng-controller="MainCtrl">

    {{ obj }}

    <dir>
      <input type="text" ng-model="obj" />
    </dir>

  </body>

为什么当我使用obj更改自定义指令中的ng-transclude范围变量时,我不会在MainCtrl $scope.obj中更改它。

但是当我在$scope.obj = { name : 'test' };MainCtrl时,双向绑定按照我期望的方式工作。

查看工作DEMO

<body ng-controller="MainCtrl">

    {{ obj.name }}

    <dir>
      <input type="text" ng-model="obj.name" />
    </dir>

  </body>

这种行为有什么解释?

3 个答案:

答案 0 :(得分:2)

从子作用域访问父作用域上的原始变量存在问题。您有一个子范围,因为transclude: true创建了一个新范围。

你真的应该阅读this article以深入了解正在发生的事情。

文章的重点:

  

范围继承通常是直截了当的,你通常不会   甚至需要知道它正在发生......直到你尝试双向数据绑定   (即表格元素,ng-模型)到基元(例如,数字,字符串,   boolean)在子范围内从父范围定义。

  

通过遵循以下内容,可以轻松避免使用原语这个问题   &#34;最佳实践&#34;总是有一个&#39;。在您的ng模型中。

当涉及到基元时,不会查询父作用域。它是一个Javascript的东西,甚至不是Angular的。

我还创建了一个隐藏子范围的Demo对象。 (遮蔽非原始对象):

app.directive('dir', function () {
    return {
        restrict: 'E',

        scope: true,
        template: "<div><input type=\"text\" ng-model=\"obj.name\" /></div>",
        link: function(scope, element, attrs) {
          scope.obj = {name : "newname"}; 
        }

    };
});

答案 1 :(得分:0)

当写入这个新属性(MainCtrl)时,被转换的html会生成obj的子范围,子范围会生成一个覆盖父级的新范围。

  

不会查询原型链,并且会向childScope添加新的aString属性。这个新属性使用相同的名称隐藏/隐藏parentScope属性。

修改后的版本有效,因为子范围(transcluded)首先访问obj(引用),然后访问属性名称

详细了解https://github.com/angular/angular.js/wiki/Understanding-Scopes

的范围继承

http://angular-tips.com/blog/2014/03/transclusion-and-scopes/

处的翻译和范围行为

答案 2 :(得分:0)

当您从同一范围查询obj的值时,这是有效的 - 指令的范围:

<body ng-controller="MainCtrl">

  {{ obj }}

  <dir>
    <p>
      The following text will be synched with the model:
    </p>
    <span>{{ obj }}</span>
    <br/>
    <input type="text" ng-model='obj' />
  </dir>

</body>