【问题标题】:AngularJS watchers still firing after element removed with jQuery?使用 jQuery 删除元素后,AngularJS 观察者仍然触发?
【发布时间】:2018-06-23 05:21:35
【问题描述】:

我有一个类似电子表格的表格设置,它使用表格元素构建,这些表格元素使用角度来启用编辑,包括行选择/删除功能。 这是一个 html,如果它“被选中”,它可以突出显示一行:

    <tr row-id="0" ng-class="selectedClass(5)" class="ng-scope budget-row">
      <td>
        <label id="foo" ng-hide="some_function(5)">{{row(5).value}}</label>
        <input type="text" ng-hide="!some_function(5)">
      </td>
      <td>...</td>
    </tr>

ng-class="selectedClass(5)" 用于在选中时为行应用背景色。

一旦选择了一行,就可以“剪切”它。在作用域上调用 cut 方法,它会移除底层的 row 对象并从 Dom 中移除元素,如下所示:

 let el = angular.element("#foo");
 let deleteTarget = el.parent().parent();
 deleteTarget.remove();

这一切在页面上都可以正常工作,但我可以在控制台和堆栈跟踪中看到,即使从页面中删除了已删除的行,ng-class 指令仍然明显地触发它们。虽然它现在工作正常,但如果所有已删除的行仍在通过角度检查更改,即使它们不再出现在页面上,我可以看到它变得非常慢。

这是从已删除的元素调用“isSelected”函数的堆栈跟踪。

isSelected (budget_items.self-e32480dfbdba1522e84f3891a1bef58643f758332acf63bc6a7e4b06bfee6b49.js?body=1:688)
$scope.selectedClass (budget_items.self-e32480dfbdba1522e84f3891a1bef58643f758332acf63bc6a7e4b06bfee6b49.js?body=1:50)
fn (VM700:4)
expressionInputWatch (angular.self-78d77e4a3c91d5788f4be38711bc43955307738d52116f065bc1289f6abc3523.js?body=1:16661)
$digest (angular.self-78d77e4a3c91d5788f4be38711bc43955307738d52116f065bc1289f6abc3523.js?body=1:18364)
$apply (angular.self-78d77e4a3c91d5788f4be38711bc43955307738d52116f065bc1289f6abc3523.js?body=1:18641)
(anonymous) (angular.self-78d77e4a3c91d5788f4be38711bc43955307738d52116f065bc1289f6abc3523.js?body=1:27469)
dispatch (jquery3.self-5af507e253c37e9c9dcf65064fc3f93795e6e28012780579975a4d709f4074ad.js?body=1:5184)
elemData.handle (jquery3.self-5af507e253c37e9c9dcf65064fc3f93795e6e28012780579975a4d709f4074ad.js?body=1:4992)

【问题讨论】:

  • 像这样混合 jQuery 和 AngularJS 是自找麻烦。

标签: jquery angularjs


【解决方案1】:

AngularJs 使用名为:$destroy 的特殊事件来删除观察者并进行所有清理工作。当你使用 jQuery 时,Angular 不会被通知应该删除某些东西。这就是问题的根源。

所以你有两个选择:

  1. 使用标准 AngularJs 工具,例如 ng-if
  2. 创建一个桥接指令,该指令将捕获删除事件并通知 AngularJs。如何使用 $destroy 描述了here。如何处理 DOM 节点删除事件描述 here

是的,混合 AngularJs 和 jQuery 甚至原生 DOM API 会给你带来很多问题

【讨论】:

  • 我考虑过使用 ng-if,但在我看来,为了让 ng-if 正常工作,即使在我不再需要该行之后,它也必须评估条件。我所做的本质上是一个编辑程序,通过将 ng-if 中定义的表达式设置为 false 来使事情消失,这意味着被删除的行永远存在,以防万一 ng-if 在某个时候评估为 true。这似乎不是最理想的,因为我将有很多垃圾行坐在内存中的某个地方,即使它们已经被处理掉,也会在每个周期进行评估。我误解了什么?
  • 你是对的。使用动态模板并不容易。我可以提供创建一个角度包装器。在包装器之外,您将传递数据和所有角度人员,但在内部您将处理 jQury。这将帮助您区分这两种方法。我会尝试这种方式。
  • 任何示例都会非常有用。我似乎无法弄清楚如何使用破坏,如链接中所示,因为我通过编译插入 dom 的 html 字符串来创建每一行。这些示例似乎建议破坏“删除元素的范围”,但在我的情况下,每一行都从根范围上的一个对象获取其值(来自预算对象维护的集合行的“行”。使用像 {{ budget.row(6).subtotal}} 和类似的。那么我如何摆脱编译步骤创建的所有这些观察者呢?
  • 哦,很简单,使用 {{::budget.row(6).subtotal}} 创建一次性绑定。这将只评估一次表达式并在之后立即销毁观察者。
  • 这只是一个开始,但是在更改行中的其他单元格后,该行会重新计算。我想要做的是破坏删除绑定。任何线索如何做到这一点?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多