【问题标题】:Angularjs detect directives on new DomAngularjs 检测新 Dom 上的指令
【发布时间】:2015-05-22 10:49:50
【问题描述】:

您好,我一直在开发 Angular 应用程序。我怀疑 angularjs 在添加新 DOM 时是否检测到指令。

让我们假设我有一个名为 mention 的 Angular 指令,当 Dom 有一个名为 mention 的类时编译它

当一个新的 Dom 被添加到 class <a class="mention">Hello</a>mention 时。角度指令是否检测到这个 DOM。

如果不是,如何在这个新的 DOM 上绑定一个事件。考虑以下场景。

var app = angular.module('app')
app.controller('Home',function ($scope, $timeout){
  $timeout( function () {
    $(".main").append("<a class='mention'> </a>"));
    }, 5000);
app.directive('mention', function() {
  return {
    restrict: 'AEC',
    transclude: true,
    link: function (scope, element, attb) {

    },
    template: '<h1> AT mentions </h1>'
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app="app" class='main' ng-controller="Home">
  
  </div>

【问题讨论】:

  • 是的,Angular 使用 $digest 循环来查看新的 DOM 节点

标签: javascript jquery angularjs dom angularjs-directive


【解决方案1】:

Angular 不知道添加了新的 DOM,也不会在这些 DOM 元素上调用指令。为了让 Angular 熟悉新的 DOM,您应该将其编译为新模板。以下是您的代码的外观:

JavaScript

angular.module('app', []).
  controller('ctrl', function($scope, $timeout, $compile) {
    $timeout(function() {
      $(".main").append(
        $compile("<a class='mention'>some text</a>")($scope)
      );
    }, 500);
  }).
  directive('mention', function() {
    return {
      restrict: 'AEC',
      transclude: true,
      link: function (scope, element, attb) {

      },
      template: '<h1> AT mentions <ng-transclude></ng-transclude></h1>'
    }
  });

Plunker

http://plnkr.co/edit/Q4Th2XU52MbOp6vRrjAs?p=preview

您可以像往常一样将事件绑定到新的 DOM:

$(".main").append(
    $compile("<a class='mention'>some text</a>")($scope)
).on('click', function() {
    $window.alert('click')
});

http://plnkr.co/edit/F9esG9YTRF2B25IP1alg?p=preview

除此之外,您提供的代码中还有多个问题:

  • var app = angular.module('app') 应该是 var app = angular.module('app',[]) 来声明新模块而不是获取它;
  • 您在使用 jQuery 添加新 DOM 的行中放置了额外的右括号
  • 您应该在控制器代码之外定义新指令
  • 带有transclude:true 的指令在模板中应该有&lt;ng-transclude&gt;&lt;/ng-transclude&gt;

注意

直接在 Angular 中操作 DOM 是一种不好的做法。仅在指令的 linkcompile 函数中或您别无选择时执行此操作(例如,无法修改的第三方代码应与 Angular 集成)。

【讨论】:

    【解决方案2】:

    回答这个问题:。 Angular 在每个$digest 循环中循环您的DOM elements,因此如果将创建一个附加指令的新节点,那么angular 确实会看到并初始化该指令。

    修改你的代码这一切似乎与$有关,它超出了angular scope。您是否尝试过像这样将append 包裹在$apply

    $scope.$apply(function () {
        $(".main").append("<a class='mention'> </a>");
    }
    

    【讨论】:

    • 但是我的指令功能不起作用。它没有绑定到新的 DOM
    • 您是在告诉angular,您的指令是class。您也应该发布指令代码,以便我们查看
    • 请检查上述情况。
    • 现在它是使用 $timeout 添加的,它具有角度范围。
    • @DanMoldovan 不幸的是,你在这两点上都错了:Angular 不会在每个 $digest 循环中循环遍历 DOM 元素,它会遍历 $scope 树来检测更改。 Angular 在每次执行 $timeout 后运行 $digest 循环,因此将运行在 $timeout 内部的代码包装到 $scope.$apply 中没有任何效果。
    猜你喜欢
    • 2014-05-29
    • 1970-01-01
    • 2016-07-07
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 2013-06-14
    相关资源
    最近更新 更多