如何在使用 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>
在组件之间切换
我们有两个组件,<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>