这是开始页面:
<!DOCTYPE html>
<html>
<head>
<script>document.write('<base href="/app/" />');</script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>App</title>
</head>
<body>
<my-app>
Loading...
</my-app>
<!-- 1. Load libraries -->
<!-- IE required polyfills, in this exact order -->
<script src="/cp/node_modules/es6-shim/es6-shim.min.js"></script>
<script src="/cp/node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="/cp/node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>
<script src="/cp/node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="/cp/node_modules/systemjs/dist/system.src.js"></script>
<script src="/cp/node_modules/rxjs/bundles/Rx.js"></script>
<script src="/cp/node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="/cp/node_modules/angular2/bundles/router.dev.js"></script>
<script src="/cp/node_modules/angular2/bundles/http.dev.js"></script>
<!-- 2. Configure SystemJS -->
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('app/main')
.then(null, console.error.bind(console));
</script>
</body>
</html>
此组件(startComponent
)加载应用程序的根页:
@Component({
selector: 'my-app',
templateUrl: 'app/mainPage.html',
directives: [RouterOutlet,RouterLink,ROUTER_DIRECTIVES],
providers: [
ROUTER_PROVIDERS,
HTTP_PROVIDERS
]
})
页面mainPage.html
包含:
<div id="content">
<a [routerLink]="['NextPage']">NextPage</a>
<my-content></my-content>
</div>
当我们转到NextPage
链接时,请启动此组件:
@Component({
selector: 'my-content',
templateUrl: 'app/nextPage.html'
})
export class NextPageComponent implements OnInit {
public str = "";
constructor() {}
ngOnInit() {
this.getStr();
}
getStr(){
this.str = "abc";
}
}
NextPageComponent
应该在由my-content
的组件创建的选择器startComponent
中插入一行“abc”。
但不知何故,他在选择器abc
的末尾插入了my-app
行,而不是my-content
。
也就是说,最后我们得到以下页面:
<my-app>
<div id="content">
<a [routerLink]="['NextPage']">NextPage</a>
<my-content></my-content>
</div>
<my-content _ngcontent-quv-2=""><div>abc</div></my-content>
</my-app>
但是,我想在结果中得到这样一个页面:
<my-app>
<div id="content">
<a [routerLink]="['NextPage']">NextPage</a>
<my-content><div>abc</div></my-content>
</div>
</my-app>
为什么会这样?我做错了什么?
答案 0 :(得分:1)
Router在内部使用DynamicComponentLoader(请参阅Router's source code)动态实例化组件(这个名称几乎就是这么说的)。
它专门使用loadNextToLocation
和文档状态
loadNextToLocation(...)
创建Component的实例并将其附加到在指定为ElementRef的位置找到的View容器。
如您所见,它将Component附加到视图中。它没有检查视图以查看它是否与其中的某些内容相匹配,因此,无论您是否有一些与选择器匹配的元素,它都会工作,因为再次,路由器它没有寻找任何东西在视图中,它在视图中附加了组件,换句话说就是它推动它。
让我们自己尝试这种行为。让我们在一些组件中查看一些与某些动态组件选择器匹配的元素
@Component({
selector : 'dynamic-cmp',
template : 'Dynamic template'
})
class DynamicCmp {}
@Component({
selector: 'my-app',
template : `
<dynamic-cmp></dynamic-cmp> <!-- Element matching DynamicCmp selector -->
<dynamic-cmp></dynamic-cmp> <!-- Element matching DynamicCmp selector -->
`
})
export class App {
constructor(private _dcl: DynamicComponentLoader, private _eRef: ElementRef) {}
ngOnInit() {
this._dcl.loadNextToLocation(DynamicCmp, this._eRef);
}
}
Plnkr以及上面的示例
注意:我没有在指令属性中添加DynamicCmp
当您运行该示例并查看DOM时,您将看到此
<my-app>
<dynamic-cmp></dynamic-cmp>
<dynamic-cmp></dynamic-cmp>
</my-app>
<dynamic-cmp _ngcontent-ybo-2="">Dynamic template</dynamic-cmp>
有两个空的dynamic-cmp
元素,即使它们与动态组件的选择器匹配。
这正是路由器的作用,这也是您看到此行为的原因。路由器不依赖于视图(它不会查找匹配的选择器),也不依赖于指令,它会动态地将组件(推送它们)加载到指定的视图中。
我希望这能澄清一下发生了什么。