【问题标题】:$destroy is not being called when element is removed from DOM从 DOM 中删除元素时不会调用 $destroy
【发布时间】:2015-07-22 13:43:44
【问题描述】:

我有一个添加到表单的指令,我需要知道何时从 DOM 中删除表单。我正在尝试使用 $destroy 事件来检测它,但是当我在元素上调用 .remove() 时,不会触发 $destroy 事件。

我做错了吗?是否有正确的方法来判断它何时从 DOM 中删除?

相关代码:

HTML:

<form id="myform" form-watch>

在控制器中:

var form = document.getElementById('myform');
// DOES NOT trigger $destroy
form.remove();

// DOES trigger $destroy
//angular.element(form).scope().$destroy();

指令:

app.directive('formWatch', function () {
  return {
    restrict: 'A',
    link: function(scope, element) {
        scope.$on('$destroy', function() {
            alert('destroyed');
        });
    }
  };
});

这是plunker

编辑:这是我正在使用的更准确的图片:new plunker

【问题讨论】:

  • 需要意识到在这种情况下范围是控制器范围,因为指令没有使用隔离范围。控制器仍然处于活动状态,因此删除元素不会破坏控制器范围。另外为什么不使用ng-if 而不是操纵DOM?控制器中不应该有任何 dom 操作代码。你到底想做什么?
  • 注明。本质上,该应用程序到处都有可点击的组件,单击一个会用一个值(在表单中)替换只读显示以提交更改。我正在使用这个 form-watch 指令来跟踪页面范围的“编辑”状态。如果某些原因导致表单被删除,我需要知道我不再编辑。
  • 更有理由使用范围模型或 $state 来控制该 dom 元素的存在。如果你自己在做这种 dom 操作,那就大错特错了
  • 在我的辩护中,这是别人的错误。你能通过使用范围模型来扩展你的意思吗?
  • 简单示例...表单在自己的控制器中,但也可以是具有隔离范围的指令,也可以是嵌套视图plnkr.co/edit/V4jVMWBO4ifsiIn6kE0v?p=preview

标签: javascript angularjs dom


【解决方案1】:

我不太确定您真正关心的是实际的销毁事件本身,而是应用程序中知道表单何时存在或不存在的一种方式。

这应该通过应用程序中的控制器和服务进行监控。

我认为的问题是正在进行不应该存在的 dom 操作......通过使用适当的范围模型并设计仅由范围模型驱动的视图,角度应该可以完成几乎所有的 dom 操作,如果不是全部。

以下示例通过将表单包装在其自己的控制器中并使用ng-if 和范围变量来确定表单是否存在,从而实现您想要的警报:

app.controller('MainCtrl', function($scope) {
  $scope.showForm = true;
});

app.controller('FormCtrl', function($scope) {
  $scope.$on('$destroy', function() {
    alert('destroyed');
  });
});

HTML:

<body ng-controller="MainCtrl">
  <!-- form has it's own controller -->
  <form ng-if="showForm" ng-controller="FormCtrl"></form>

 <!-- button in MainCtrl scope -->
 <button ng-click="showForm = !showForm">Toggle form</button>

每当ng-if 删除表单时,FormCtrl 作用域就会被销毁并触发$destroy 事件。然而,观察决定表单存在的范围变量可能是你真正想要的

DEMO

【讨论】:

  • 您上面提到的指令也可以,但对我来说似乎不起作用。这是我正在使用的更准确的图片:plnkr.co/edit/UvhZbflqKJY2YcCWnR6U
  • 另外,值得注意的是应用程序中有很多不同的“点击编辑”指令,这就是为什么我试图通过删除表单来保持它尽可能简单-watch 指令。
  • 好吧...没有 DOM 操作也一样...在同一个 isEditing 变量 plnkr.co/edit/dlmBnpnBSNGLrrdmbDFU?p=preview 上简单地添加 ng-if 代码实际上更简单,并且可以满足您的期望。 .throw 警报
  • 签出x-editable ...很棒的点击也可以使用角度模块进行编辑
  • 越来越近了,谢谢。我可以访问指令控制器中的元素(表单)吗?还是表单控制器?使用此解决方案,我如何处理监视表单的 $dirty 属性?
【解决方案2】:

作用域销毁不会自动连接到 DOM - 所以如果你想手动删除指令,IMO 正确的方法是调用 $destroy() 然后显式删除任何相关的 dom。

所以我会将元素的删除移至 $destroy 回调并使用您已有的代码触发它

angular.element(form).scope().$destroy();

在你的指令中

scope.$on('$destroy', function() {
    element.remove();
});

HTH

【讨论】:

    猜你喜欢
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 2020-07-07
    • 2015-02-04
    相关资源
    最近更新 更多