angularjs - AngularJS 中指令隔离范围与 ng-repeat 范围

标签 angularjs angularjs-directive angularjs-scope angularjs-ng-repeat

我有一个带有隔离范围的指令(以便我可以在其他地方重用该指令),并且当我将此指令与 ng-repeat 一起使用时,它无法工作。

我已阅读有关此主题的所有文档和 Stack Overflow 答案并了解这些问题。我相信我已经避免了所有常见的问题。

所以我知道我的代码由于 ng-repeat 创建的范围而失败。指示。我自己的指令创建一个隔离范围,并对父范围中的对象进行双向数据绑定(bind)。我的指令将为这个绑定(bind)变量分配一个新的对象值,当我的指令在没有 ng-repeat 的情况下使用时,这可以完美地工作。 (父变量已正确更新)。然而,与 ng-repeat ,赋值在 ng-repeat 中创建一个新变量范围和父变量看不到变化。根据我所读到的内容,这一切都符合预期。

我还读到,当给定元素上有多个指令时,只会创建一个作用域。那是priority可以在每个指令中设置来定义指令的应用顺序;指令按优先级排序,然后调用它们的编译函数(在 http://docs.angularjs.org/guide/directive 搜索单词优先级)。

所以我希望我可以使用优先级来确保我的指令首先运行并最终创建一个隔离范围,并且当 ng-repeat 时运行时,它会重新使用隔离作用域,而不是创建一个典型地从父作用域继承的作用域。 ng-repeat文档指出该指令以优先级 1000 运行。尚不清楚是否1是较高优先级或较低优先级。当我使用优先级1时在我的指令中,它没有什么区别,所以我尝试了 2000 。但这让事情变得更糟:我的双向绑定(bind)变成 undefined我的指令不显示任何内容。

我创建了a fiddle to show my issue 。我已经注释掉了priority在我的指令中设置。我有一个名称对象列表和一个名为 name-row 的指令显示名称对象中的名字和姓氏字段。单击显示的名称时,我希望它设置 selected主作用域中的变量。名称数组,selected变量被传递到 name-row使用双向数据绑定(bind)的指令。

我知道如何通过调用主作用域中的函数来使其工作。我也知道如果selected在另一个对象内部,并且我绑定(bind)到外部对象,事情就会起作用。但我目前对这些解决方案不感兴趣。

相反,我的问题是:

  • 如何预防 ng-repeat创建一个原型(prototype)继承自父作用域的作用域,然后让它使用我的指令的隔离作用域?
  • 为什么是优先级 2000我的指令不起作用?
  • 使用 Batarang,是否可以知道正在使用的范围类型?

最佳答案

好吧,通过上面的大量评论,我发现了其中的困惑。首先,澄清几点:

  • ngRepeat 不会影响您选择的隔离范围
  • 传递到 ngRepeat 以便在指令属性上使用的参数确实使用原型(prototype)继承范围
  • 您的指令不起作用的原因与隔离范围无关

下面是相同代码但删除了指令的示例:

<li ng-repeat="name in names"
    ng-class="{ active: $index == selected }"
    ng-click="selected = $index">
    {{$index}}: {{name.first}} {{name.last}}
</li>

这是一个JSFiddle证明它行不通。您将获得与指令中完全相同的结果。

为什么不起作用?因为 AngularJS 中的作用域使用原型(prototype)继承。父作用域中selected 的值是基元。在 JavaScript 中,这意味着当子进程设置相同的值时,它将被覆盖。 AngularJS 范围中有一条黄金法则:模型值中应该始终包含一个.。也就是说,它们永远不应该是原始类型。请参阅this SO answer了解更多信息。

<小时/>

这是示波器最初的样子的图片。

enter image description here

单击第一项后,范围现在如下所示:

enter image description here

请注意,在 ngRepeat 作用域上创建了一个新的 selected 属性。 Controller 范围 003 未更改。

您可能会猜到当我们单击第二项时会发生什么:

enter image description here

<小时/>

所以你的问题实际上根本不是由 ngRepeat 引起的 - 它是由违反 AngularJS 中的黄金法则引起的。解决这个问题的方法是简单地使用对象属性:

$scope.state = { selected: undefined };
<li ng-repeat="name in names"
    ng-class="{ active: $index == state.selected }"
    ng-click="state.selected = $index">
    {{$index}}: {{name.first}} {{name.last}}
</li>

这是一个second JSFiddle显示这也有效。

以下是范围最初的样子:

enter image description here

点击第一个项目后:

enter image description here

这里, Controller 作用域按照需要受到影响。

此外,为了证明这仍然适用于具有隔离范围的指令(因为这与您的问题无关),这里有一个 JSFiddle为此, View 也必须反射(reflect)对象。您会注意到,唯一必要的更改是使用对象而不是基元

最初的范围:

enter image description here

单击第一项后的范围:

enter image description here

总结:再一次,您的问题不在于隔离范围,也不在于 ngRepeat 的工作方式。您的问题是您违反了已知会导致此问题的规则。 AngularJS 中的模型应该始终有一个 ..

关于angularjs - AngularJS 中指令隔离范围与 ng-repeat 范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15623698/

相关文章:

javascript - 为什么 ng-keypress 不会更改 ng-model 值

javascript - 如何在不更改整个列表的情况下编辑列表中的项目?

javascript - AngularJS 嵌套 ng-repeat

javascript - 无法从 Modal 元素获取 $file,Angular JS

angularjs - Angular 指令 - 在链接方法中定义的模板函数的属性中调用函数时出现插值问题

javascript - Angular ng-repeat 的调用输入焦点更改

javascript - 切换按钮的指令

angularjs - ng-controller ng-model 和 $scope 如何在任何地方使用 angularjs 变量

javascript - AngularJS Resolve 等待外部图像加载完成

javascript - AngularJS 等待标签加载到 DOM 中