对Angularjs感到困惑,并将其范围和范围分开。绑定

时间:2013-05-20 15:34:11

标签: angularjs angularjs-directive angularjs-scope

我正在努力理解模型的范围及其对范围有限的指令的约束。

我认为限制指令的范围意味着控制器。$ scope和directive.scope不再是同一个东西。但是,我对如何在指令模板或html中放置模型影响数据绑定感到困惑。我觉得我错过了一些非常基本的东西,继续前进我需要理解这一点。

采用以下代码(在此处小提琴:http://jsfiddle.net/2ams6/

的JavaScript

var app = angular.module('app',[]);
app.controller('Ctrl',function($scope){
});
app.directive('testel', function(){
    return {
        restrict: 'E',
        scope: {
            title: '@'
        },
        transclude: true,
        template:   '<div ng-transclude>'+
                    '<h3>Template title: {{title}}</h3>' +
                    '<h3>Template data.title:{{data.title}}</h3>' +
                    '</div>'
    }    
}); 

HTML

<div ng-app='app'>
    <div ng-controller="Ctrl">
        <input ng-model="data.title">
        <testel title="{{data.title}}">
            <h3>Transclude title:{{title}}</span></h3>
            <h3>Transclude data.title:{{data.title}}</h3>
        </testel>
    </div>
</div>

模型仅更新模板中的{{title}},并在翻译中更新{{data.title}}为什么不在转换中{{title}}或在模板中{{data.title}}

将输入移动到翻译中,如此(在此处小提琴:http://jsfiddle.net/eV8q8/1/):

<div ng-controller="Ctrl">
    <testel title="{{data.title}}">
        <input ng-model="data.title">
         <h3>Transclude title: <span style="color:red">{{title}}</span></h3>

         <h3>Transclude data.title: <span style="color:red">{{data.title}}</span></h3>

    </testel>
</div>

现在意味着只有转化{{data:title}}才会更新。 为什么不选择模板{{title}}{{data.title}},也不转换{{title}}

最后,将输入移动到模板中,就像这样(在这里小提琴:http://jsfiddle.net/4ngmf/2/):

template: '<div ng-transclude>' +
            '<input ng-model="data.title" />' +
            '<h3>Template title: {{title}}</h3>' +
            '<h3>Template data.title: {{data.title}}</h3>' +
            '</div>'

现在意味着只有模板{{data.title}}得到更新。 同样,为什么不是其他3个绑定?

我希望有一些明显的东西让我盯着我,我想念它。如果你让我得到这个,我会给你买啤酒,或给你一些积分,或其他一些这样的东西。非常感谢。

3 个答案:

答案 0 :(得分:113)

你的小提琴创造了三个范围:

  1. 与控制器Ctrl关联的范围,因为ng-controller
  2. 由于transclude: true
  3. 指令转换范围
  4. 指令隔离范围,因为scope: { ... }
  5. 在fiddle1中,在我们在文本框中输入任何内容之前,我们有以下内容:

    enter image description here

    范围003是与控制器关联的范围。由于我们尚未输入文本框,因此没有data属性。在隔离范围004中,我们看到创建了title属性,但它是空的。它是空的,因为父作用域还没有data.title属性。

    在文本框中输入my title之后,我们现在有了:

    enter image description here

    控制器范围003现在有一个新的data对象属性(这就是它为黄色的原因),其title属性现在设置为my title。由于隔离范围属性title是单向数据绑定到内插值data.title,因此它也会获得值my title(该值因为更改而变为黄色。)

    转换范围原型继承自控制器范围,因此在转换HTML中,angular可以跟随原型链并在父范围中找到$scope.data.title(但$scope.title不存在)。

    隔离范围只能访问自己的属性,因此只能访问属性title

    在小提琴2中,在输入之前我们有与fiddle1相同的图片。

    输入my title后:

    enter image description here

    注意新data.title属性出现的位置 - 在转换范围内。隔离范围仍在控制器作用域上查找data.title,但这次不存在,因此其title属性值保持为空。

    在小提琴3中,在输入之前我们有与fiddle1相同的图片。

    输入my title后:

    enter image description here

    注意新data.title属性出现的位置 - 在隔离范围上。其他任何范围都不能访问隔离范围,因此字符串my title不会出现在其他任何位置。


    Angular v1.2的更新:

    随着更改eed299a Angular现在会在转化之前清除转换点,因此Template title: ...Template data.title: ...部分不会显示,除非您修改模板ng-transclude本身就是:

    '<h3>Template title: <span style="color:red">{{title}}</span></h3>' +
    '<h3>Template data.title: <span style="color:red">{{data.title}}</span></h3>' +
    '<div ng-transclude></div>'
    

    在Angular v1.3的以下更新中,进行了此模板更改。


    Angular v1.3 +的更新:

    自Angular v1.3起,transcluded范围现在是指令的隔离范围的子代,而不是控制器范围的子代。所以在fiddle1中,在我们输入任何内容之前:

    enter image description here

    此更新中的图片是使用Peri$scope工具绘制的,因此图片略有不同。 @表示我们有一个使用@语法的隔离范围属性,粉红色背景意味着该工具无法找到映射的祖先引用(这是真的,因为我们没有' t输入文本框中的任何内容。)

    在文本框中输入my title之后,我们现在有了:

    enter image description here

    使用@绑定的隔离属性将始终在@符号后的隔离范围中显示插值字符串结果。 Peri $ scope也能够在祖先范围内找到这个确切的字符串值,因此它还显示了对该属性的引用。

    在小提琴2中,在输入之前我们有与fiddle1相同的图片。

    输入my title后:

    enter image description here

    注意新data.title属性出现的位置 - 在转换范围内。隔离范围仍在控制器作用域上查找data.title,但这次不存在,因此其title属性值保持为空。

    在小提琴3中,在输入之前我们有与fiddle1相同的图片。

    输入my title后:

    enter image description here

    注意新data.title属性出现的位置 - 在隔离范围上。即使被转换的范围可以通过$parent关系访问隔离范围,它也不会查找titledata.title - 它只会查看控制器范围(即,它将遵循原型继承),并且控制器范围没有定义这些属性。

答案 1 :(得分:22)

在阅读了所有提出的答案后,包括马克的精彩原理图,这是我对范围的理解,也是我对问题的继承。我希望评论这个图表的位置,以便我可以适当更新。我希望它只是对马克所呈现的内容提供了不同的观点:

Scope inheritance

答案 2 :(得分:8)

好问,顺便问一下!希望我的回答是雄辩的......

答案与被饶恕的元素如何获得其范围有关。

总结一下,你有两个范围:

  1. 控制器的范围,$scope.data.title。 (由input元素隐式添加)
  2. 指令的范围,具有$scope.title
  3. 当您更改控制器的$scope.data.title时,指令的$scope.title也会发生变化。

    您还有两个HTML部分,即被转换的模板和模板。发生的事情是,被转换的HTML位于控制器的范围内,而模板HTML位于指令的范围内。因此,转化的HTML对title一无所知,模板范围对data.title

    一无所知

    这实际上就是Transclusion的目的 - 允许指令的子元素保持其父范围,在这种情况下是控制器的范围。根据设计,被转换的元素不知道它们在指令中,因此无法访问指令的范围。

    另一方面,指令模板只能访问指令的范围。

    我已经改变了一些代码,使名称更清晰(但功能相同)

    http://jsfiddle.net/yWWVs/2/

相关问题