Как разработчик Angular в течение нескольких лет, я столкнулся с фреймворком Aurelia в моем текущем проекте для компании в Барневельде, Нидерланды. Я ничего не знал об Аурелии, и, вероятно, так же, как и вы, я даже не слышал об этом раньше ...

Прямо сейчас я занимаюсь разработкой с Aurelia в течение года и должен сказать, что мне очень нравится этот фреймворк. По сравнению с Angular (который мне тоже очень нравится), это намного проще и быстрее выполнять задачи, и, что еще важнее, намного стабильнее (нам не пришлось вносить некоторые изменения в наш проект из-за критических изменений структуры в течение года !).

Чтобы показать вам, насколько простой и элегантный фреймворк, позвольте мне показать вам пример того, что мне пришлось реализовать на прошлой неделе:

  • У нас есть страница с (например) кнопкой, которая должна открывать боковую панель;
  • В зависимости от некоторых данных на странице нам необходимо динамически составить модель представления с соответствующим шаблоном внутри боковой панели. Итак, для этого примера, допустим, нам нужно выбрать одну из двух разных моделей представления с их собственными шаблонами (ViewModelOne и ViewModelTwo);
  • Мы создаем SidePanelController, который управляет боковой панелью, конечно, и использует Event Aggregator Аурелии для отправки событий, таких как open и close.
  • И, наконец, SidePanel, который подписывается на эти события и составляет модель представления внутри боковой панели.

Простая страница с кнопкой
Начнем со страницы, простой страницы с кнопкой, которая вызывает SidePanelController с моделью представления в качестве аргумента.

Для шаблона:

<template>  
  <button click.delegate="buttonClicked()">Open Side Panel</button></template>

..и для модели просмотра:

import { autoinject } from 'aurelia-framework';
import { SidePanelController } from 'side-panel.controller';
import { ViewModelOne } from './view-model-one';
import { ViewModelTwo } from './view-model-two'; 
@autoinject()
export class SomePage {  
  constructor(private sidePanelController: SidePanelController) {
  }
  public buttonClicked(): void {
    const viewModel = new ViewModelOne(); // or ViewModelTwo
    this.sidePanelController.open(viewModel);
  }
}

SidePanelController
Мы создали нашу страницу, которая внедрила SidePanelController с помощью инъекции зависимостей Aurelia. Контроллер может выглядеть примерно так:

import { autoinject } from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';

@autoinject()
export class SidePanelController {
  constructor(private ea: EventAggregator) {
  }

  public open(viewModel: any): void {
    this.ea.publish('side-panel:open', { viewModel });
  }

  public close(): void {
    this.ea.publish('side-panel:close', {});
  }
}

Мы могли бы расширить этот контроллер, чтобы добавить такие функции, как выталкивание и выталкивание моделей представлений, чтобы затем контроллер отслеживал все модели представлений, отправляя и выталкивая их из стека и обратно. Затем боковая панель будет повторяться для всех моделей представления, составлять их и с помощью некоторой магии CSS складывать их друг на друга, анимируя их внутри и снаружи нашей боковой панели. Позже я покажу вам краткий пример.

Давайте создадим нашу боковую панель
Вот здесь и произойдет волшебство, это так красиво и элегантно, как теперь мы можем скомпоновать модель представления внутри нашей боковой панели. Поскольку эти фрагменты кода являются всего лишь примерами, мы сохраняем их простыми и понятными. Но вы увидите всю красоту этого и возможности, которые он вам откроет.

<template>
  <div class="side-panel">
    
    <div class="side-panel__header">
      Side Panel
      
      <!-- this will close the side panel -->
      <a click.delegate="close()">Close</a>
    </div>
    
    <div class="side-panel__body">
      
      <!-- this is where the view models will be composed -->
      <compose view-model.bind="viewModel">
    </div>
    
  </div>
</template>

Посмотреть модель боковой панели:

import { autoinject } from 'aurelia-framework';
import { 
  EventAggregator, 
  Subscription 
} from 'aurelia-event-aggregator';

@autoinject()
export class SidePanel {
  public viewModel: any;
  public isOpen: boolean;
  private subscriptions: Set<Subscription>;

  constructor(private ea: EventAggregator) {
    this.viewModel = null;
    this.isOpen = false;
    this.subscriptions = new Set<Subscription>();
  }
    
  // Aurelia's attached lifecycle hook
  public attached(): void {
    const openHandler = (data: any) => this.handleOpenEvent(data);
    const openSubscription = this.ea
      .subscribe('side-panel:open', openHandler);
    
    const closeHandler = () => this.handleCloseEvent();
    const closeSubscription = this.ea
      .subscribe('side-panel:close', closeHandler);
    
    this.subscriptions.add(openSubscription);
    this.subscriptions.add(closeSubscription);
  }
    
  // Aurelia's detached lifecycle hook
  public detached(): void {
    this.subscriptions.forEach(subscription => (
      subscription.dispose()
    );  
  }
  
  private handleOpenEvent({ viewModel }: EventData): void {
    this.viewModel = viewModel;
    this.isOpen = true;
  }
  
  private handeCloseEvent(): void {
    this.viewModel = null;
    this.isOpen = false;
  }
}

И точно так же Aurelia создаст модель представления, найдет с ней соответствующий шаблон (на основе имени файла и местоположения), и все будет работать!

Чтобы реализовать наложение страниц на боковой панели, вы можете просто добавить модели представления к Array или Map в SidePanel и повторить их на боковой панели следующим образом:

<template>
  <div class="side-panel">
    
    <div class="side-panel__header">
      <!-- this will pop the last view model from stack -->
      <a click.delegate="pop()">Back</a>
      
      Side Panel
      
      <!-- this will close the side panel -->
      <a click.delegate="close()">Close</a>
    </div>
    
    <div class="side-panel__body">
      <!-- where the view models will be composed -->
      <div class="side-panel__stacked-page" 
           repeat.for="viewModel of viewModels">
        
        <compose view-model.bind="viewModel">
      </div>
    </div>
    
  </div>
</template>

Что ж, надеюсь, вам понравилось читать мой первый пост и вы убедились в красоте фреймворка. Аурелия не популярна и, вероятно, никогда ею не станет. Его не поддерживает какая-то огромная компания. На мой взгляд, это фреймворк для разработчиков от разработчиков. Поскольку я работал с обоими фреймворками Aurelia и Angular, я продолжаю наслаждаться тем, насколько проста Aurelia по сравнению с Angular.

Щелкните здесь, чтобы просмотреть все материалы на GitHub.

Спасибо за прочтение!