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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 16:53:41  来源:igfitidea点击:

Instance Angular 2 Component Two times

javascripttypescriptangular

提问by Pablo

I'm trying to learn Angular 2, so I was making some hello worldexamples. 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-worldcustom 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 appto 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 bodyas root selector for your Angular2 app.

当然,如果在您的 HTML 中您需要有其他内容(非应用程序内容或其他bodyAngular 应用程序),您就不会选择作为 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. enter image description here

看看屏幕截图。 在此处输入图片说明

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 loadingat the end of the bottom of the picture.

如您所见,loading图片底部的末尾有一个。

However, it works for non-main components. As you can see my-hero-detailcomponents 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>