Подтвердить что ты не робот

Как реализовать сайт с сотнями страниц в Angular2

Я готовлю сайт SPA, содержащий сотни страниц, похожих на статьи (помимо электронной коммерции, логин и т.д.). Каждая статья имеет свой собственный URL. Я хочу это реализовать, используя Angular2. Единственное решение, которое я нашел до сих пор:

1. подготовить сотни компонентов Agular2, один компонент для каждой статьи...

... с templateUrl, указывающим на разметку статьи. Поэтому мне понадобятся сотни компонентов, похожих на:

@core.Component({
  selector: 'article-1',
  templateUrl: 'article1.html'
})
export class Article1 {}

2. для отображения статьи с использованием AsyncRoute

см. Ленивая загрузка компонентов маршрута в Angular2

@core.Component({
  selector: 'article-wrapper',
  template: '<router-outlet></router-outlet>'
})
@router.RouteConfig([
  new router.AsyncRoute({
    path: '/article/:id',
    loader: () => {
      switch (id) {
        case 1: return Article1;
        case 2: return Article2;
          //... repeat it hundreds of times
      }
    },
    name: 'article'
  })
])
class ArticleWrapper { }

В Angular1 существует директива ngInclude, которая отсутствует в Angular2 из-за проблем безопасности (см. здесь).

[Редактировать 1] Существует не только проблема с самим кодом. Проблема также в статической природе этого решения. Если мне нужен сайт с картой сайта и динамической структурой страницы - добавление отдельной страницы требует перекомпиляции всего модуля JavaScript ES6.

[Edit 2] Концепция "разметка x html как данные" (где разметка - это не только статический HTML, но и HTML с активными компонентами) - это базовая концепция всей сети (каждая CMS имеет свои данные разметки в базе данных). Если для него не существует решения Angular2, оно отрицает это основное понятие. Я считаю, что должен существовать какой-то трюк.

4b9b3361

Ответ 1

Все следующие решения сложны. Официальная проблема поддержки Angular здесь.

Благодаря @EricMartinez для указания на @alexpods solution:

this.laoder.loadIntoLocation(
  toComponent(template, directives), 
  this.elementRef,
  'container'
);

function toComponent(template, directives = []) {
  @Component({ selector: 'fake-component' })
  @View({ template, directives })
  class FakeComponent {}

  return FakeComponent;
}

И еще одно подобное (из @jpleclerc):

@RouteConfig([
  new AsyncRoute({
    path: '/article/:id',
    component: ArticleComponent,
    name: 'article'
  })
])
...

@Component({ selector: 'base-article', template: '<div id="here"></div>', ... })
class ArticleComponent {
    public constructor(private params: RouteParams, private loader: DynamicComponentLoader, private injector: Injector){

    }

    ngOnInit() {
      var id = this.params.get('id');
      @Component({ selector: 'article-' + id, templateUrl: 'article-' + id + '.html' })
      class ArticleFakeComponent{}

      this.loader.loadAsRoot(
          ArticleFakeComponent, 
          '#here'
          injector
      );
    }
}

Немного отличается (от @peter-svintsitskyi):

// Faking class declaration by creating new instance each time I need.
        var component = new (<Type>Function)();
        var annotations = [
            new Component({
                selector: "foo"
            }),
            new View({
                template: text,
                directives: [WordDirective]
            })
        ];

        // I know this will not work everywhere
        Reflect.defineMetadata("annotations", annotations, component);

        // compile the component
        this.compiler.compileInHost(<Type>component).then((protoViewRef: ProtoViewRef) => {
            this.viewContainer.createHostView(protoViewRef);
        });