如何在使用 ng-transclude 的组件之间切换?

How to switch between components that uses ng-transclude?

在组件之间切换

我们有两个组件,<hello></hello><goodbye></goodbye>。这两个组件都有包含,允许它们以 <hello>World</hello><goodbye>World</goodbye>.

等方式使用
angular
  .module('myApp', [])
  .component('hello', {
    template: '<h1>Hello, <ng-transclude></ng-transclude>!</h1>',
    transclude: true
  })
  .component('goodbye', {
    template: '<h1>Goodbye, <ng-transclude></ng-transclude>!</h1>',
    transclude: true
  });

现在,我们希望能够在使用 <hello></hello> 组件或 <goodbye></goodbye> 之间切换。可以做到这一点的一种方法是使用 ng-if(Fiddle)

script.js

...
.controller('MyController', ['$scope', function($scope) {
  $scope.component = 'hello';
}]);

index.html

<div ng-controller="MyController">
    <hello ng-if="component === 'hello'">World</hello>
    <goodbye ng-if="component === 'goodbye'">World</goodbye>
</div>

重复代码问题

但是,如果我们的嵌入包含更多行呢?我们可能有 <hello><!-- Many lines which we'd rather not repeat twice --></hello> 而不是简单的 <hello>World</hello>。如果我们使用相同的方法来做这件事,我们最终会得到很多重复的代码。所以如果我们可以简单地使用 "switch out" 组件就好了。 (Fiddle)

<div ng-controller="MyController">
    <hello ng-if="component === 'hello'">
    <goodbye ng-if="component === 'goodbye'">
    Lorem Ipsum.........
    </goodbye>
    </hello>
</div>

不幸的是,这没有按预期工作。设置 $scope.component = 'hello' 会产生 Hello, !,而设置 $scope.component = 'goodbye' 会产生空白页。我对此行为的解释是 angularjs 将其解析为嵌套在 <hello></hello> 中的 <goodbye></goodbye>,而不是在使用 <hello></hello><goodbye></goodbye> 之间切换。所需的行为更符合 if-else if 语句。

我也尝试过使用 ng-switch on(Fiddle)

<div ng-controller="MyController">
  <div ng-switch on="component">
    <hello ng-switch-when="hello">
    <goodbye ng-switch-when="goodbye">
    Lorem Ipsum.........
    </goodbye>
    </hello>
  </div>
</div>

但是,这会产生多指令资源争用错误。

Error: $compile:multidir

Multiple Directive Resource Contention

Multiple directives [ngSwitchWhen, hello] asking for transclusion on: <hello ng-switch-when="hello">

类似问题

来自问题 Using ng-transclude inside ng-switch, the Github Issue 声称已经修复了类似的错误。但是,修复仅适用于 ng-transclude 嵌套在 <div></div> 块中的情况,如下所示:

<div ng-controller="MyController">
  <div ng-switch on="component">
    <div ng-switch-when="hello">
      <hello>Lorem Ipsum.........</hello>
    </div>
    <div ng-switch-when="goodbye">
      <goodbye>Lorem Ipsum.........</goodbye>
    </div>
  </div>
</div>

不幸的是,这不会解决我之前描述的重复代码问题。

所以我的问题是

有没有办法在保持嵌入代码不变的同时切换组件,而不必多次重写嵌入代码?

如果不是,我可以使用哪些替代方法来实现我的目标,同时将重复代码的数量保持在最低限度?

解决此问题的一个方法是将 <!-- Many lines which we'd rather not repeat twice --> 放入另一个组件中。 (Fiddle)

.component('common', {
  template: 'Lorem Ipsum.........'
})

现在,唯一重复的代码是组件的标记。

<div ng-controller="MyController">
  <hello ng-if="component === 'hello'"><common></common></hello>
  <goodbye ng-if="component === 'goodbye'"><common></common></goodbye>
</div>

如果不需要额外的组件,也可以对 ng-include 执行相同的操作。

<div ng-controller="MyController">
  <hello ng-if="component === 'hello'"><ng-include src="'common.html'"></ng-include></hello>
  <goodbye ng-if="component === 'goodbye'"><ng-include src="'common.html'"></ng-include></goodbye>
</div>