在Angular + UI Bootstrap中创建隔离范围的问题

时间:2014-02-18 22:21:07

标签: javascript angularjs twitter-bootstrap

我有一个简单的数据表,使用AngularJS创建。表中的一列是根据控制器上的函数计算的。

我在页面上有一个按钮,可以打开一个新模态。当我使用UI引导打开模态时,我得到一个新的孤立范围(根范围的子),如预期的那样。但是,如果我在模态中有输入文本,则此文本字段中的任何按键都会自动调用父作用域上的函数 - 即使我可以验证作用域是否已隔离。

以下是行为的一部分:http://plnkr.co/edit/JzhxSDcSefDe04Psxq0w

如示例所示,表的第三列是使用名为“ageNextYear”的函数计算的。在呈现表时,会按预期多次调用此函数(并且可以在控制台日志中进行验证)。但是,如果我打开模态并在字段中键入一些文本,则仍会调用父作用域上的“ageNextYear”函数(在输入字段中键入一些文本并观察控制台日志输出)。

我不确定这是否是预期的行为,或者我是否做错了什么。我尝试在两个作用域上使用点表示法,并明确地将新作用域传递给$ modal.open,但没有任何乐趣。

我可以解决这个问题(通过在“人员”上创建一个watchCollection并以这种方式更新表格 - 这可能是一种更好的方式来做到这一点)但是想验证其他人是否也看到了这种行为。

2 个答案:

答案 0 :(得分:3)

您遇到的问题与模态对话框的范围无关。该问题与在ng-repeat表达式中使用函数有关。通常,在表达式中使用函数是一个性能问题,但它在ng-repeat中是一个更大的问题。根据这篇关于common pitfalls of using scopes

的优秀文章
  

在视图或观察者中使用表达式时,您应该始终记住每次AngularJS认为需要时都会调用表达式。使用函数不会获得最佳性能,甚至可能会错过一些更改事件。

     

这意味着表达......

     
      将分别为每个项目调用ng-repeat内的
  1. 。此外,repeat指令使用它来确定数据更改。
  2.   
  3. 可以在一个摘要中多次评估。当您使用多个指令或其他范围观察者时,可能会发生这种情况。
  4.   
  5. 即使直接范围似乎没有变化,也可以进行评估。
  6.   
  7. 如果函数的返回值发生更改,则不会计算包含函数,但仅在函数定义发生更改时才会计算。
  8.   

您的示例会导致其中3个发生。

  1. 您为范围中的每个对象重复函数调用,3个项目= 3次调用函数。
  2. 您可以通过调用模态对话框间接添加其他观察程序。
  3. 对模态对话框范围内数据的更改会导致评估包含ng-repeat的控制器的范围,即使ng-repeat中的数据没有改变(也无法知道数据是否已更改)直到$ digest被调用)。对模态的每次更改都会导致$ digest,这会导致另一次通过ng-repeat,以及对ng-repeat中每个项目的另一次调用。
  4. 在您的情况下,每次计算表达式时都不需要运行逻辑。当逻辑结果发生变化时,最好计算逻辑并将其写入范围。这将逻辑与对象和视图分离。

    总结,

      

    最佳做法:

         
        
    • 请勿在表达式中使用函数。
    •   
    • 请勿在表达式中使用范围之外的其他数据。
    •   
    • 在应用外部数据更改时,请使用$ scope。$ apply()。
    •   

答案 1 :(得分:1)

西蒙 我喜欢你的问题,我在范围上添加了监视,并看到了摘要周期被称为

$ scope。$ watch(功能watchMe(范围){console.log('摘要看着我!');});

以下是带摘要的fork。 http://plnkr.co/edit/5PTO1uPFvmLrg7K9vzTm?p=preview

我不知道这是原因,但我认为ng-repeat中的表达式正在调用摘要,因为它试图评估该项目上任何事件的表达式。

我认为我们应该评估模型中的表达式,并将更新的模型提供给ng-repeat以解决问题。