Angular 不正确地将隔离指令的范围与服务器呈现的内容联系起来



我正在开发一个在服务器渲染的HTML之上使用角度的Web应用程序。

我正在尝试将呈现的 HTML 的一部分用作可重用组件(指令),因此我在返回的 HTML 中的相应标记上附加了一个属性指令。此指令需要具有独立作用域,并且它将进一步包含应是此隔离指令中的子作用域的子指令。

不幸的是,angular 没有从返回的 HTML 创建具有正确作用域层次结构的指令。独立作用域内的子指令是独立作用域的同级指令(而不是子指令)。现在,如果我将这些指令更改为使用客户端模板,它可以正常工作。因此,似乎angular 不喜欢从服务器生成的 HTML 构造这种形式的指令。

为了更好地说明我的问题,我创建了几个 plunker - 一个工作正常(客户端模板),另一个工作不正确(服务器渲染的 HTML)。

服务器渲染的 plunker

索引.html

<body>
  <div isolate-dir>
    Content from the server
    <div child-dir>
      More content from the server: <span ng-bind="testVar">server data</span>
    </div>
  </div>
</body>

脚本.js

angular.module('test', []);
angular.module('test').directive('isolateDir', function() {
  return {
    restrict: 'A',
    scope: {},
    link: function(scope, element, attr) {
      console.log('isolate dir scope [' + scope.$id + ' -> ' + scope.$parent.$id + ']');
    }
  }
});
angular.module('test').directive('childDir', function() {
  return {
    restrict: 'A',
    scope: true,
    link: function(scope, element, attr) {
      console.log('child dir scope [' + scope.$id + ' -> ' + scope.$parent.$id + ']');
      scope.testVar = "client data";
    }
  }
});

输出

child dir scope [3 -> 1]
isolate dir scope [2 -> 1]

客户端模板 Plunker

索引.html

<body>
  <div isolate-dir></div>
</body>

脚本.js

angular.module('test', []);
angular.module('test').directive('isolateDir', function() {
  return {
    restrict: 'A',
    scope: {},
    link: function(scope, element, attr) {
      console.log('isolate dir scope [' + scope.$id + ' -> ' + scope.$parent.$id + ']');
    },
    template: "Content from the server <div child-dir></div>"
  }
});
angular.module('test').directive('childDir', function() {
  return {
    restrict: 'A',
    scope: true,
    link: function(scope, element, attr) {
      console.log('child dir scope [' + scope.$id + ' -> ' + scope.$parent.$id + ']');
      scope.testVar = "client data";
    },
    template: "More content from the server: <span ng-bind='testVar'>server data</span>"
  }
});

输出

child dir scope [3 -> 2]
isolate dir scope [2 -> 1]

运行 plunkers 并观察控制台输出时,您可以看到范围层次结构在客户端模板化版本中是正确的,而在服务器呈现版本中不正确。

为什么服务器呈现的内容的范围层次结构不正确,解决此问题的最佳方法是什么?

好消息是这与"服务器"渲染无关。

问题来自您对指令的理解。隔离指令(isolate-dir)确实会有一个孤立的作用域,这会影响它的模板和控制器。但是,HTML 层次结构与 Angular 范围层次结构没有关系:只有 <div isolate-dir> 具有隔离的作用域,但不是其所有子元素

如果您希望子元素继承自该父div的作用域,则应将这些子元素放入隔离指令的模板中(这是在您的第一个示例中完成的,因此它有效),或者使用提供给link函数的transclusion参数将父作用域传播到其内部元素。

这是使用此方法的 plunkr:

plnkr.co/edit/n0ws7pPqOS8dt6IMKYMl?p=info

如果这仍然让您感到困惑,您可以在此处阅读更多相关信息:

http://angular-tips.com/blog/2014/03/transclusion-and-scopes/

最新更新