Angular指令的作用域问题
Angular directives &scope issues
我正在使用一个预先存在的模板,试图将其角化。
我有3个指令,基本上是一个card,一个card-header和card-body:
<card>
<card-header title="My Card">
<input type="text" ng-model="userSearch" />
</card-header>
<card-body>
<card ng-repeat="item in object | filter:userSearch">
<card-body>{{ item.name }}</card-body>
</card>
</card-body>
</card>
我相信你能看到这个问题…由于范围问题,我无法让过滤器拾取模型。因为我在指令中有自己的html,所以我需要使用transclude: true
,并且根据我的理解,它创建了自己的作用域。
卡:
return {
restrict: 'AE',
transclude: true,
replace: true,
scope: false,
template: '<div class="card" ng-transclude></div>',
}
卡头:
return {
restrict: 'AE',
requires: 'card',
transclude: true,
replace: true,
scope: false,
scope: {
title: '@',
secondary: '@',
theme: '@'
},
template: '<div class="card-header" ng-class="theme"><h2 ng-if="title">{{ title }}<small>{{ secondary }}</small></h2><div ng-transclude></div></div>',
}
卡身体:
return {
restrict: 'AE',
requires: '^card',
transclude: true,
replace: true,
scope: false,
scope: {
padding: '@',
theme: '@'
},
template: '<div class="card-body" ng-class="theme" ng-transclude></div>',
link: function($scope, $element, $attributes) {
if($scope.padding)
angular.element($element[0]).addClass('card-padding');
}
}
似乎应该是一个简单的概念,但我不知道如何才能绕过这个,当我有我自己的作用域项,但需要跨界和有我自己的作用域项。
首先,我认为你可能有标记问题。我想你的意思是:
<card>
<card-header title="My Card">
<input type="text" ng-model="userSearch" />
</card-header>
<card-body>
<card ng-repeat="item in object | filter:userSearch">
<card-body>{{ item.name }}</card-body>
</card>
</card-body> <!--this was card-header, which doesn't make sense -->
</card>
当你在指令中使用ng-transclude时,被transclude的内容会使用一个新的作用域,它是指令作用域的兄弟。因此,如果您要分析您的作用域树,那么您将拥有以下内容(A是整个块的父作用域,()表示隔离作用域):
<card A>
<card-header A.B.(C)>
<input A.B.D ng-model="A.B.D.userSearch">
</card-header>
<card-body A.E.(F)>
<card A.E.G.H ng-repeat="A.E.G.H.item in A.E.G.object | filter: A.E.G.userSearch">
<card-body A.E.I.(J)>{{A.E.I.K.item.name}}
</card>
</card-body>
</card>
注意一些事情(除了明显的"这有很多作用域!"):
A.B.D.userSearch是一个与A.E.G.userSearch完全不同的属性。a.e.g.在原型上不继承a.b.d,这就是为什么过滤器不起作用。
还需要注意的是,A.E.G.H.item和A.E.I.K.item是不同的属性——这也行不通。
如何修复:
最简单的修复方法是不使用ng-transclude,而是使用手动transclude,并控制transclude内容所使用的作用域。
例如,卡片传输将更改为:
template: '<div class="card" transclude-target></div>'
link: function(scope, element, attr, ctrl, transclude) {
transclude(scope, function(clone, scope){
element.find('[transclude-target]').append(clone);
}
}
Aside: ng- translude:
link: function(scope, element, attr, ctrl, transclude) { transclude(scope.$parent.$new(), function(clone, scope){ element.find('[ng-transclude]').append(clone); } }
这样做的目的是使透传使用指令作用域而不是指令作用域的兄弟作用域(甚至是一个新作用域)
作用域树变成:
<card A>
<card-header A.(B)>
<input A.(B) ng-model="A.(B).userSearch">
</card-header>
<card-body A.(C)>
<card A.(C) ng-repeat="A.(C).D.item in A.(C).object | filter: A.(C).userSearch">
<card-body A.(C).D>{{A.(C).D.item.name}}</card-body>
</card>
</card-body>
</card>
仍然不完全正确(孤立的指令破坏了我们需要的继承链)。
将其他两个指令(card-header和card-body)改为使用scope.$parent:
link: function(scope, element, attr, ctrl, transclude) {
transclude(scope.$parent, function(clone, scope){
element.find('[transclude-target]').append(clone);
}
}
生成下面的作用域树(现在你的过滤器可以工作了{{item.name}}应该会显示正确的版本)
<card A>
<card-header A.(B)>
<input A ng-model="A.userSearch">
</card-header>
<card-body A.(C)>
<card A.E ng-repeat="A.E.item in A.object | filter: A.userSearch">
<card-body A.E.(D)>{{A.E.item.name}}
</card>
</card-body>
</card>
我肯定我在某个地方犯了一个错误,但我认为它应该解释发生了什么。我希望我的解释更简单,但这是我能做的最好的了。
这是我对你的问题的理解:
如果检查最后一个指令,我看到的是模板中没有定义模型。
现在当你指定模板时,它会替换指令元素中的html,所以你的模型没有出现的原因。
也就是说,如果item.name在card-body指令中,则必须在模板中包含model。现在当你使用ng-transclude时,它会把原来的html放回去,这就是为什么你能在某种程度上解决问题(但范围导致问题)。
您必须按照如下方式更改模板,并且必须在隔离作用域定义中也包含item。
template: '<div class="card-body" ng-class="theme">{{item.name}}</div>'
如果你不想修改它,并且想使用ng- translude,有两种方法可以从子作用域调用父作用域变量,
- 使用作用域对象的属性。
所以不是项作为$scope。你可以用一个对象来代替它as属性:$scope.itemModel.items
现在如果你修改这些,它们也会反映在父作用域。由于自然,它更快javascript .
- 不推荐,但是你可以使用$parent在视图和控制器中。
检查这些是否适合你
- AngularJS$作用域在选项卡集中出现问题
- 作用域问题-此函数是否形成闭包-JavaScript
- 访问Javascript对象-Node.js的作用域问题
- 尝试将变量传递到对象中时的作用域问题'的方法构造函数
- “this”和内部作用域命名函数的打字稿问题
- 'simple'套接字中的作用域问题.IO服务器
- 我对按钮的作用域有问题'的听众
- Javascript作用域问题,对象在分配后没有数据
- 在DOM(html)上下文中使用角度作用域函数时出现的问题
- 可能存在Javascript作用域问题
- 本地Javascript作用域问题
- 设置Javascript函数的作用域问题
- AngularJS:图片上传+文件阅读器预览.控制器、指令和作用域之间的绑定出现问题
- 作用域和将参数传递给动态创建的事件处理程序时出现问题
- 达到 10 次摘要迭代,中止(作用域函数问题)
- Javascript 中使用 setTimeout 的作用域问题
- 作用域问题反应父子方法ES6
- jquery get中的作用域问题
- 当输入具有带作用域的指令时,Angularjs绑定会出现问题
- 绑定时出现Javascript作用域问题