【问题标题】:Why isn't $destroy triggered when I call element.remove?为什么我调用 element.remove 时没有触发 $destroy?
【发布时间】:2014-07-10 02:21:03
【问题描述】:

我不明白为什么在下面的示例中没有触发 $destroy 事件。谁能解释一下为什么不触发,什么情况下会触发?

这里是 plunkr:http://plnkr.co/edit/3Fz50aNeuculWKJ22iAX?p=preview

JS

angular.module('testMod', [])
.controller('testCtrl', function($scope){
  $scope.removeElem = function(id) {
    var elem = document.getElementById(id);
    angular.element(elem).remove();
  }
}).directive('testDir',[function() {
  return {
    scope:true,
    link: function(scope) {
      console.log('in directive');
      scope.$on('$destroy', function(){
        alert('destroyed');
      })
    }
  }
}]);

HTML

<body ng-controller='testCtrl'>
  <div testDir id='test'>I will be removed.</div>
  <button ng-click='removeElem('test')'>remove</button>
</body>

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    问题是您在scope 上监听$destroy 事件,但$destroy 正在element 上触发。

    来自 angular.js 源代码(我确信它在网站上的某个地方有文档,但我没有看):

    $destroy - AngularJS 拦截所有 jqLit​​e/jQuery 的 DOM 破坏 api 并在所有被删除的 DOM 节点上触发此事件。这个可以 用于清理之前与 DOM 元素的任何 3rd 方绑定 它已被删除。

    您的指令应该是(注意我添加了scopeelementattrs 作为link 参数):另外,这是一个plunker

    directive('testDir',[function() {
      return {
        scope:true,
        link: function(scope,element,attrs) {
          console.log('in directive');
          element.on('$destroy', function(){
            alert('destroyed');
          })
        }
      };
    }]);
    

    【讨论】:

    • 有道理,我自己应该意识到这一点:)
    • 作为后续,我是否应该在元素的 $destroy 事件中手动销毁该指令的范围?会处理吗?
    • @TimMac 您如何建议我在这里手动销毁范围?
    • @WebWanderer 你可以在作用域上调用$destroy() 方法,我在元素destroy 事件和作用域destroy 事件上都这样做了。
    • @TimMac 这就是我的想法。感谢您的安慰。
    【解决方案2】:

    我很困惑为什么 $destroy 事件没有在 remove() 方法上触发。

    根据文档,$destroy 事件在两种情况下触发。

    1. 就在作用域被销毁之前
    2. 就在从 DOM 中删除元素之前

    目的是“清理”。您可以监听 $destroy 事件并在销毁范围或元素之前执行必要的清理。 ngIf、ngSwitch、ngRepeat 和其他内置指令/方法使用 $destroy 事件来执行清理。

    最好的例子是 ngRepeat 指令

    https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js

    在第 339 行,您可以注意到 $destroy 事件被触发。您可以在从 ngRepeat 使用的列表中删除项目之前监听事件并执行任何操作。

    ngRepeat $destroy 示例 Plunk -- http://goo.gl/mkozCY

    【讨论】:

    • 这样做会破坏控制器的$scope,而不是被删除元素的隔离范围。
    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 2022-07-03
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多