【问题标题】:AngularJS ng-if not deleting element after $compileAngularJS ng-if 在 $compile 之后不删除元素
【发布时间】:2017-01-28 19:35:14
【问题描述】:

我有一个执行以下指令的指令:

  1. 向元素添加另一个指令属性。
  2. 删除自己的属性。
  3. 在元素上调用 $compile() 以使 AngularJS 重新编译元素,从而附加新指令。

这很好用,除非我还向元素添加了 ng-if。请参阅此最小示例并按照以下步骤进行演示。

https://embed.plnkr.co/ymk0RwGopGF1KvesWmvA/

  1. +任意次数以添加到“计数”。
  2. 0 重置“计数”。
  3. 再按任意次数+

我希望“显示的我的测试”<p> 标记在第 2 步之后一旦其ng-if 条件不再为真,就会从 DOM 中删除。相反,它会一直存在,您会在第 3 步之后看到消息的额外副本。

我假设在 my-test 指令链接函数中调用 $compile($element)($scope); 会产生一些意想不到的后果,但我不明白这里发生了什么。有什么想法吗?

谢谢, 大卫

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-compile


    【解决方案1】:

    据我所知,当您将 count 的值更改为 0 时,您的指令会在更改 count 的值之前被销毁。所以未删除指令的计数值仍然是 1。

    如果你使用 ngShow 而不是 ngIf,你可以解决这个问题。因为 ngShow 属性不会触发 $destroy 事件并且不会从您的视图中删除元素。因此该指令可以捕获该count 的新值。或者您可以使用prelink 而不是link 来捕获count 值的更新。

    【讨论】:

    • 我在发布之前也尝试过 ng-show,我同意它解决了简约示例中的问题。然而,在我的真实应用程序中,有些情况需要实际使用 ng-if,例如可见时需要的表单输入。
    • @DavidSmith 现在我想起来了。您可以将 link 属性重命名为 prelink。在此更改之后,您的 ngIf 将能够捕获 count 的值。你可以通过这种方式解决这个问题。
    【解决方案2】:

    正如其他人回答的那样,简短的解决方案是使用 ng-show 而不是 ng-if 或不使用 $compile 这样。除此之外,您可能有充分的理由要像这样使用ng-if$compile

    这个问题让我感兴趣的是使用$compileng-if 的隔离范围。我对this fork 做了一些试验,并将尝试解释我的发现。

    我们已经知道ng-if 创建了一个隔离作用域,但随后通过$compile 传递带有ng-if 的元素会创建另一个 隔离作用域(并使新编译的ng-if正在查看第一轮隔离范围内的变量 - 指令的 $scope 值)。

    重申一下,我们的一些作用域看起来像([] 中的值是作用域.$id):

    1. 主/外控制器有scope[2]

    2. ng-if my-test 元素具有ng-if 查看scope[2].count 并创建scope[3]

    3. my-test 链接器因此具有$scope.$id == 3;

    4. my-test 执行$compile - 重新编译ng-if 元素:创建新隔离scope[4] 并查看scope[3].count

    5. scope[2].count 达到0 - scope[3] 得到$destroyed(因为scope[3] 是由第一个ng-if 创建的,它仍然在某个地方徘徊)......但是!元素是 A. 仍然存在 B. 它的计数没有更新 - 为什么?

    好吧,因为仍然存在的元素是 $compiled 并且有一个 ng-if 查看 scope[3].count(现在是 $destroyed)和 B.它自己的新隔离 scope[4](创建通过使用父 scope[3] 重新编译 ng-if 元素)

    所以你。这一切都非常令人困惑,您可能只是在问……我该如何解决这个问题?

    TL;DR;

    最简单的解决方案: $element.removeAttr('ng-if'); 在你做之前$compile($element)($scope);

    如果您一直在关注,这是因为原来的 ng-if 仍在查看 scope[2].count,并且存在的元素不再获得第二个隔离范围。

    【讨论】:

    • 这很有帮助,谢谢。其他内置指令是否会创建像 ng-if 这样的隔离范围?如果我碰巧在我的指令旁边使用 ng-repeat 甚至是自定义/第 3 方指令,我是否可能再次遇到同样的问题?
    • 很高兴它有帮助!一些内置和第 3 方指令确实创建了隔离范围。您只需要查看您计划使用的每个指令的文档。例如,ng-if docs 说“此指令创建新范围”。 (在指令信息部分下)与ng-repeat docs 一样,但您会看到ng-show(例如)没有。
    【解决方案3】:

    我不知道如何正确解释,但 ng-if 为元素添加了一个新范围,即他自己的范围,请检查此问题以查看更多详细信息:what is the difference between ng-if and ng-show/ng-hide。我尝试使用 ng-show 并按照您想要的方式工作:

    ng-show="count > 0"
    

    希望对你有帮助 =)

    【讨论】:

      猜你喜欢
      • 2018-09-15
      • 1970-01-01
      • 2023-03-14
      • 2014-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      相关资源
      最近更新 更多