【问题标题】:Forcing AngularJS directive to link outside digest cycle强制 AngularJS 指令链接外部摘要循环
【发布时间】:2018-07-03 02:15:57
【问题描述】:

这是指 Angular 1 应用程序。

如果 DOM 在我的 Angular 应用程序的上下文之外被修改,我知道我可以使用 angular.element(document.body).scope().$apply() 强制重新渲染整个应用程序,包括新注入的内容。

但是我的指令似乎永远不会链接。

所以在下面的例子中,标记<message></message> 应该呈现Hello World,但是当它被手动注入,然后应用摘要时,link 方法似乎永远不会运行。

https://jsbin.com/wecevogubu/edit?html,js,console,output

javascript

var app = angular.module('app', [])

app.directive('message', function() {
  return {
    template: 'Hello, World!',
    link: function() {
      console.log('message link')
    }
  }
})

document.getElementById('button').addEventListener('click', function() {
  document.getElementById('content').innerHTML = '<message>default content</message>'
  var scope = window.angular.element(document.body).scope()
  scope.$apply()
})

html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
</head>
<body ng-app="app">
  inside app:
  <message></message>

  outside app:
  <button id="button">Print another message</button>
  <div id="content"></div>
</body>
</html>

【问题讨论】:

  • 您认为 $apply 会强制整个应用程序重新渲染(包括新注入的内容)的想法是错误的。 $apply 仅在检测到任何更改时触发所有观察者及其侦听功能。这些更改将更新之前编译的指令的 DOM。 $apply 不会编译和链接新指令。

标签: javascript angularjs


【解决方案1】:

根据文档,您可以使用angular.injector 进行此操作

angular.injector 允许您在应用程序启动后注入和编译一些标记

所以您的示例代码可能是:

document.getElementById('button').addEventListener('click', function() {
  var $directive = $('<message>default message</message>');
  $('#content').append($directive);

  angular.element(document.body).injector().invoke(function($compile) {
    var scope = angular.element($directive).scope();
    $compile($directive)(scope);
  });
})

希望这就是你要找的东西!

【讨论】:

  • 我相信这有正确的答案,但我也认为$compile是这里的关键,注射器几乎与问题无关,不应该成为这里的重点。例如,您可以将指令放在控制器执行的范围内:$scope.compile = $compile;,然后从外部 document.getElementById('content').innerHTML = scope.compile("&lt;message&gt;...&lt;/message&gt;")(scope)[0].innerHTML
  • @ippi 感谢您指出这一点,正如您提到的,$compile 是这里的关键,injector 是从外部访问它的一种方式。
  • 请注意,编译会将观察者添加到范围。在从 DOM 中删除元素时,如果没有计划删除这些观察者,代码将产生内存泄漏。
  • 谢谢大家,这正是我想要的!有趣的是,我过去确实使用过这个,但显然忘记了。
猜你喜欢
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-22
  • 2017-05-09
  • 1970-01-01
相关资源
最近更新 更多