Javascript 实例 Angular 2 组件两次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34818238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Instance Angular 2 Component Two times
提问by Pablo
I'm trying to learn Angular 2, so I was making some hello world
examples.
Here is my code:
我正在尝试学习 Angular 2,所以我做了一些hello world
例子。这是我的代码:
boot.ts
启动文件
import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './app.component'
import {DataService} from './app.dataservice'
bootstrap(AppComponent, [DataService]);
index.html
索引.html
...
<body>
<hello-world>Loading...</hello-world>
<hello-world>Loading...</hello-world>
</body>
...
app.component.ts
app.component.ts
import {Component} from 'angular2/core';
import {DataService} from './app.dataservice'
@Component({
selector: 'hello-world',
template: '<h1>Hello {{ item }}</h1>'
})
export class AppComponent {
items: Array<number>;
item: number;
constructor(dataService: DataService) {
this.items = dataService.getItems();
this.item = this.items[0];
}
}
app.dataservice.ts
app.dataservice.ts
export class DataService {
items: Array<number>;
constructor() {
this.items = [1,2,3];
}
getItems() {
return this.items;
}
}
The code seems to work fine since the first hello-world
custom tag is being correctly showed with the code inside the ts
. However, the second hello-world tag is not transformed
. Only one custom element is shown.
该代码似乎工作正常,因为第一个hello-world
自定义标记与ts
. 然而,第二个hello-world tag is not transformed
. 仅显示一个自定义元素。
Can't be more than 1 custom tag? How can I do that?
不能超过 1 个自定义标签?我怎样才能做到这一点?
EDIT
编辑
I have added the new import inside app.components.ts
我在 app.components.ts 中添加了新的导入
import {ByeWorld} from './app.byeworld';
and in app.byeworld.ts
并在app.byeworld.ts
import {Component} from 'angular2/core';
@Component({
selector: 'bye-world',
template: '<h1>Bye World</h1>'
})
export class ByeWorld {
constructor() {
}
}
采纳答案by Sasxa
Just as standard HTML page should have one <body>
tag for content and one <head>
tag for 'metadata', an Angular2 application should have one root tag. To make app work you have to initialize it (tell Angular that it is an app) and you do that by calling bootstrap()
function.
正如标准 HTML 页面应该有一个<body>
内容标签和一个<head>
“元数据”标签一样,Angular2 应用程序应该有一个根标签。要使应用程序工作,您必须对其进行初始化(告诉 Angular 它是一个应用程序),然后通过调用bootstrap()
函数来实现。
If it bothers you that your root tag (for example <app>
) is inside the body, you can change selector from custom tag app
to standard tag body
. If you add different component as root, like this:
如果您对您的根标记(例如<app>
)在正文中感到困扰,您可以将选择器从自定义标记更改app
为标准标记body
。如果您以 root 身份添加不同的组件,如下所示:
import {bootstrap} from 'angular2/platform/browser'
import {Component} from 'angular2/core';
import {AppComponent} from './app.component'
import {DataService} from './app.dataservice'
@Component({
selector: 'body',
directives: [AppComponent],
template: `
<hello-world>Loading...</hello-world>
<hello-world>Loading...</hello-world>
`
})
class RootComponent {}
bootstrap(RootComponent, [DataService]);
...the rest of your code should work.
...您的其余代码应该可以工作。
Of course, if in your HTML you need to have other stuff (non-app content, or other angular apps) you wouldn't select body
as root selector for your Angular2 app.
当然,如果在您的 HTML 中您需要有其他内容(非应用程序内容或其他body
Angular 应用程序),您就不会选择作为 Angular2 应用程序的根选择器。
Hope this helps you understand things better...
希望这可以帮助您更好地理解事物......
回答by Shaohao Lin
I have tested this. You can not make more than oneAngular 2 Main Components with the same name. But you can make as many as you want for non-Main components.
我已经测试过了。您不能制作多个同名的 Angular 2 主要组件。但是您可以为非主要组件制作任意数量的组件。
How can main and non-main component are differentiated?
如何区分主要成分和非主要成分?
Main component is the one that gets bootstrapped.
主要组件是被引导的组件。
Have a look of the screen shot.
My main component called: Which I made it twice in the HTML:
我的主要组件称为: 我在 HTML 中做了两次:
<body>
<my-app>Loading...</my-app>
<my-app>Loading...</my-app>
</body>
As you can see, there is a loading
at the end of the bottom of the picture.
如您所见,loading
图片底部的末尾有一个。
However, it works for non-main components. As you can see my-hero-detail
components can be created as many as I can.
但是,它适用于非主要组件。如您所见,my-hero-detail
可以尽可能多地创建组件。
<div class="center-align">
<h1>{{title}}</h1>
</div>
<div class="row" style="margin-bottom: 0;">
<div class="col s12 m6">
<div id="my-heroes" class="card">
<div class="card-header">
<span>My Heroes</span>
</div>
<div class="card-content">
<ul class="heroes">
<li *ngFor="#hero of heroes"
(click)="onSelect(hero)"
[class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
</div>
</div>
</div>
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
</div>
<div class="row">
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
</div>
My Hero Detail Component:
我的英雄细节组件:
import {Component} from 'angular2/core';
import {Hero} from '../hero';
@Component({
selector: 'my-hero-detail',
templateUrl: 'app/hero-detail/hero-detail.html',
inputs: ['hero'],
})
export class HeroDetailComponent {
public hero: Hero;
}
回答by Josh
If you come across this question and really do want two root level app instances, this can be accomplished by manually bootstrapping your root level component(s) in the NgModule ngDoBootstrap method.
如果您遇到这个问题并且确实想要两个根级应用程序实例,则可以通过在 NgModule ngDoBootstrap 方法中手动引导您的根级组件来实现。
(Note that in Angular 5+ this method may no longer be required, see this Angular PR)
(请注意,在 Angular 5+ 中可能不再需要此方法,请参阅此 Angular PR)
We first find all root elements we want to bootstrap and give them a unique ID. Then for each instance, hack the component factory selector with the new ID and trigger the bootstrap.
我们首先找到我们想要引导的所有根元素,并给它们一个唯一的 ID。然后对于每个实例,使用新 ID 破解组件工厂选择器并触发引导程序。
const entryComponents = [
RootComponent,
];
@NgModule({
entryComponents,
imports: [
BrowserModule,
],
declarations: [
RootComponent,
],
})
export class MyModule {
constructor(private resolver: ComponentFactoryResolver) {}
ngDoBootstrap(appRef: ApplicationRef) {
entryComponents.forEach((component: any) => {
const factory = this.resolver.resolveComponentFactory(component);
let selectorName;
let elements;
// if selector is a class
if (factory.selector.startsWith('.')) {
selectorName = factory.selector.replace(/^\./, '');
elements = document.getElementsByClassName(selectorName);
// else assume selector is an element
} else {
selectorName = factory.selector;
elements = document.getElementsByTagName(selectorName);
}
// no elements found, early return
if (elements.length === 0) {
return;
}
// more than one root level componenet found, bootstrap unique instances
if (elements.length > 1) {
const originalSelector = factory.selector;
for (let i = 0; i < elements.length; i += 1) {
elements[i].id = selectorName + '_' + i;
(<any>factory).factory.selector = '#' + elements[i].id;
appRef.bootstrap(factory);
}
(<any>factory).factory.selector = originalSelector;
// only a single root level component found, bootstrap as usual
} else {
appRef.bootstrap(factory);
}
});
}
}
Now, assuming our RootComponent's selector was '.angular-micro-app' this will work as expected:
现在,假设我们 RootComponent 的选择器是 '.angular-micro-app' 这将按预期工作:
<body>
<div class="angular-micro-app"></div>
...
<div class="angular-micro-app"></div>
</body>