Angular 2.0.0-alpha для тех, кто не в силах ждать

Angular 2.0.0-alpha для тех, кто не в силах ждать

581

Совершенно не так давно(5-6 марта) прошла конференция ng-conf, и много докладов на ней было посвящено будущему релизу Angular 2 , на пары из их даже проявили альфа версию. Естественно же опосля прослушивания чрезвычайно захотелось опробовать его лично. Раз для вас тоже не терпится — прошу под кат.

В данной статье мы разберёмся, где взять билд альфа версии Angular 2.0, сделаем на нём маленькое приложение — To-do list, и запустим его в браузере без полной поддержки ECMAScript 6.

Angular 2 чрезвычайно сильно различается от сегодняшней версии, переосмыслено фактически всё. Сейчас же, судя по всему, команда Angular начала плотно сотрудничать с Microsoft и разработка будет вестись на TypeScript, и опосля выхода его версии 1.5, туда будет на сто процентов включен AtScript. Почти все из различий вытекают из того, что он на всю катушку употребляет ES6 с аннотациями и типами, создатели именуют этот язык AtScript.

Приложение Angular 2 сейчас состоит из компонентов и представляет из себя их дерево. При этом раз вы соберётесь применять в собственном приложении Web-components, либо, к примеру, Polymer – то синтаксис ничем не будет различаться от использования ваших собственных Angular 2 компонентов. Сервисы сейчас тоже стали обыкновенными классами, а благодаря поддержке типизации в AtScript, инъектировать их можно по типу, без использования синтаксиса .$inject либо ngAnnotate. Мысль похожа на Web-components, даже разметка Angular 2 компонентов помещается в Shadow DOM. Сами составляющие представляют из себя ES6 классы с аннотациями, никакого специального синтаксиса как, к примеру, для директив в версии 1.х не требуется.

Давайте на данный момент попробуем сделать наше 1-ое To-do приложение и по ходу дела разберёмся, что да как.

На сейчас ни один браузер не поддерживает весь тот функционал, который нужен Angular 2 для работы, потому нам пригодится целый ворох инструментов:

rtts-assert
es6-shim
System.js
Zone.js
Traceur с опциями для поддержки инстракций

Чтоб всем желающим пощупать альфу не приходилось ставить это всё по-отдельности, создатели собрали quick start. Его можно установить набрав в папке проекта
git clone https://github.com/angular/quickstart.git
Сейчас все нужное лежит у нас в папке quickstart, а для красы добавим ещё angular-material, но применять из него будем, очевидно, лишь css
bower install angular-material
Сейчас сделаем в проекте файл index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>To Do</title>
<script src="/quickstart/dist/es6-shim.js"></script>
<link href="bower_components/angular-material/angular-material.css" rel="stylesheet" />
</head>
<body layout="row">
<style>
md-progress-circular.md-default-theme.blue .md-inner .md-right .md-half-circle {
border-right-color: #039be5;
}

md-progress-circular.md-default-theme.blue .md-inner .md-left .md-half-circle, md-progress-circular.md-default-theme .md-inner .md-right .md-half-circle {
border-top-color: #039be5;
}

md-progress-circular.md-default-theme.blue .md-inner .md-left .md-half-circle {
border-left-color: #039be5;
}

md-progress-circular.md-default-theme.blue .md-inner .md-gap {
border-top-color: #039be5;
border-bottom-color: #039be5;
}
</style>
<app flex layout="row" layout-fill>
<div layout-fill layout="row" layout-align="center center" layout-margin>
<md-progress-circular md-mode="indeterminate" class="md-default-theme blue" style="-webkit-transform: scale(1);">
<div class="md-spinner-wrapper">
<div class="md-inner">
<div class="md-gap">
</div>
<div class="md-left">
<div class="md-half-circle"></div>
</div>
<div class="md-right">
<div class="md-half-circle"></div>
</div>
</div>
</div>
</md-progress-circular>
<h4>
    To do app is loading… </h4>
</div>
</app>
<script>
System.paths = {
‘angular2/*’: ‘quickstart/angular2/*.js’,
‘rtts_assert/*’: ‘quickstart/rtts_assert/*.js’,
‘app/*’: ‘app/*.js’
};
System.import(‘app/App’);
</script>
</body>
</html>

Тут следует направить внимание на три момента:
До этого всего мы подключили файл es6-shim, в нем заботливо собрано всё перечисленное выше, что нам необходимо для пуска приложения.
На данный момент в нем содержится просто разметка со спиннером и надписью To do app is loading… она будет показываться пока ангуляр не загрузит класс компонента и не заменит эту разметку на его template. Это и будет наш основной компонент приложения. Дальше обратим внимание на элемент app.
В самом низу мы употребляли библиотеку system.js, она реализует систему загрузки модулей ES6. Поначалу при помощи System.paths мы настроили пути к .js файлам, потом с помощью System.import загрузили файл с компонентом app, а он, в свою очередь, уже и потянет за собой все нужные библиотеки и составляющие.

Сейчас сделаем папку app и положим в неё файл App.js
import {Component, Template, bootstrap, Foreach} from ‘angular2/angular2’;
import {TodoStore} from ‘app/TodoStore’;
import {ItemEditor} from ‘app/ItemEditor’;

@Component({
selector: ‘app’,
componentServices: [
TodoStore
]
})
@Template({
url: ‘app/todo.html’,
directives: [Foreach, ItemEditor]
})
class App {
constructor(store:TodoStore) {
this.store=store;
}
}

bootstrap(App);

Мы их пока не написали, потому разглядим их позднее. Поначалу мы импортируем классы Component, Template, Foreach из angular2.js, оттуда же импортируем функцию bootstrap, уже знакомую тем, кто в версии 1.x не употребляет директиву ng-app, она инициализирует основной компонент приложения, следом мы импортируем классы TodoStore из app/todoStore.js (это будет сервис, отвечающий за работу со перечнем задач и его хранение в localStorage браузера) и ItemEditor из app/item-editor.js (это будет компонент — директива, отображающий элемент перечня).
Дальше мы создаём класс App, ему в конструктор при помощи инъектора передаётся объект класса TodoStore, который мы присваиваем свойству store.

При объявлении класса мы употребляли инструкции Component и Template из angular2.js:
Component – инструкция, которая и делает класс компонентом. Свойство selector — это селектор, позволяющий найти элемент в разметке шаблона, у нас это элемент app. Свойство componentServices – это перечень классов для инъектора.
Свойство url показывает путь, где будет находиться шаблон, свойство directives показывает перечень директив, которые употребляются в разметке этого шаблона. Template – помогает указать для компонента шаблон.
В конце файла мы используем функцию bootstrap, чтоб инициализировать наш основной компонент.

Давайте сейчас сделаем файл app/TodoStore.js
export class TodoStore {
constructor() {
this.load();
}
save() {
window.localStorage[‘todoItems’]=JSON.stringify(this.items);
}
addItem(name, checked) {
this.items.push(new Item(name,checked));
}
clear() {
this.items.length=0;
}
load() {
this.items=[];
let itemsStr=window.localStorage[‘todoItems’];
if(itemsStr) {
JSON.parse(itemsStr).forEach((e) => {
this.addItem(e.name, e.checked);
});
}
}
}

class Item {
constructor (name, checked){
this.name = name;
this.checked=checked || false;
}
toggleCheck() {
this.checked=!this.checked;
}
}

У класса TodoStore есть способы save(), load(), clear(), и addItem(name, checked).
Сам перечень задач будет храниться в свойстве items. Способ load() загружает из localStorage все элементы перечня и добавляет их в items с помощью способа addItem. Способ save() сохраняет значение характеристики items в localStorage. Способ addItem(name, checked) воспринимает имя пт перечня, делает новейший объект Item и добавляет его в Items. Способ clear() очищает свойство items.

Ещё у класса есть способ toggleCheck(), который меняет значение checked на противоположное. Следом идёт объявление класса Item, конструктор воспринимает name — имя пт перечня и checked — отмечен ли он как выполненный.

Дальше создаём файл app/todo.html с шаблоном главенствующего компонента
<style>
@import "../bower_components/angular-material/angular-material.css";

.md-primary {
background-color: #039be5;
color: white;
}

md-toolbar {
background-color: #CFD8DC;
}

md-input-container {
padding-bottom: 0;
}
</style>
<div flex layout="column" layout-fill layout-margin>
<md-toolbar class="md-primary">
<h2 class="md-toolbar-tools">
<span>To do list</span>
</h2>
</md-toolbar>
<md-content layout="row" layout-align="center start" flex>
<div flex="50" flex-md="80" flex-sm="100">
<div layout="row" layout-margin flex>
<button flex class="md-button md-primary md-raised md-default-theme" (click)="store.save()">Save</button>
<button flex class="md-button md-primary md-raised md-default-theme" (click)="store.load()">Load</button>
<button flex class="md-button md-primary md-raised md-default-theme" (click)="store.clear()">Clear</button>
</div>
<div layout="row" layout-margin flex>
<md-input-container class="md-input-has-value" flex="60">
<input #newitem class="md-input" placeholder="New to do item" />
</md-input-container>
<button flex class="md-button md-primary md-raised md-default-theme" (click)="store.addItem(newitem.value)">Add new item</button>
</div>
<md-list>
<md-item *foreach="#item in store.items">
<md-item-content>
<item-editor [item]="item"></item-editor>
</md-item-content>
</md-item>
</md-list>
</div>
</md-content>
</div>
В сегодняшней версии ангуляра иногда достаточно тяжело с первого взора отличить в разметке, какой атрибут употребляется для привязки к событию, а какой для привязки данных, сейчас же всё будет видно сходу, круглые скобки () необходимы, чтоб реагировать на действия элемента либо компонента, а атрибут в квадратных скобках [] осуществляет привязку к данным, предполагается, что значение атрибута — это выражение, которое будет вычислено, а его итог будет присвоен атрибуту элемента, раз атрибут указан вообщем без всяких скобок — то предполагается, что в нём просто текстовое значение. Тут у нас есть три клавиши, которые вызывают способы хранилища store.save(), store.load() и store.clear(). Мы привязываемся к событию click каждой клавиши с помощью атрибута (click).
Дальше обратим внимание на input с атрибутом #newitem таковым образом мы сейчас можем задавать элементу имя, по которому он будет нам доступен, как в событии click клавиши ниже, где мы берём значение input’а — newitem.value и передаём его в store.addItem().
Следом идёт перечень задач, который мы вывели с помощью новейшей директивы *foreach(это подмена ng-repeat), тут, как и в input’е выше, мы написали #item, чтоб обращаться дальше к каждому элементу перечня по имени item.
Каждый элемент перечня мы собираемся выводить при помощи директивы item-editor, которой мы привязываем элемент перечня с помощью атрибута [item].

Сейчас сделаем файл app/ItemEditor.js с компонентом ItemEditor, который будет отвечать за отображение частей перечня.
import {Component, Template} from ‘angular2/angular2’;

@Component({
selector: ‘item-editor’,
bind: {
‘item’: ‘item’
}
})
@Template({
inline: `
<style>

@import "../bower_components/angular-material/angular-material.css";
md-checkbox.md-checked .md-icon {
background-color: #039be5;
color: white;
}
</style>
<md-checkbox [class.md-checked]="item.checked" (click)="item.toggleCheck()">
<div class="md-label">
<div class="md-container">
<div class="md-icon"></div>
</div>
<span>
{{item.name}}
</span>
</div>
</md-checkbox>
`
})
export class ItemEditor {

}

Тут в @Component мы указали селектор ‘item-editor’, это элемент, который употребляется в *foreach в todo.html. Следом указано свойство bind, оно показывает, что необходимо привязать значение атрибута item к свойству item класса компонента(что-то вроде bindToController).
В @Template на этот раз заместо url для примера указано свойство inline, оно служит для указания текста шаблона прямо в коде. Это понижает количество требуемых http запросов, потому опосля выхода Angular 2 быстрее всего покажется кокой-нибудь плагин для Gulp, который будет поменять url на inline, на подмену сегодняшнему gulp-angular-templatecache.

В самом шаблоне можно узреть атрибут [class.md-checked] — это лаконичная подмена ng-class. А ниже выводится имя элемента перечня с помощью уже ставшего родным синтаксиса с фигурными скобками {{item.name}}.

Вот и всё, сейчас можно запустить проект(инспектировал лишь в Хроме) и поглядеть, как работает будущий Angular 2.0.

Благодаря полностью новейшей архитектуре, сделанной с расчётом на огромные приложения, производительность рендеринга, основной бич версий 1.x, растет во много раз(приятное сопоставление можно поглядеть в конце доклада Дейва Смита Angular + React = Speed ). Как мы лицезреем, создатели на сто процентов переосмыслили концепцию Angular.js и нас сейчас ожидает полностью новейший фреймворк с новеньким, наиболее лаконичным синтаксисом. А новшества ES6 сделают разработку ещё скорее и приятнее. Возможность применять типизацию открывает перспективы развития IDE для продвинутой поддержки дополнения кода и статического анализа(как минимум, Microsoft заявляет поддержку Angular в Visual Studio одним из ценностей).

Это фактически и всё, что мне удалось выяснить о Angular 2.0 на сейчас, будем далее смотреть за новостями, а пока вот несколько и увлекательных ссылок по теме:
Канал ng-conf на YouTube с массой увлекательных докладов
Официальный веб-сайт Angular 2.0
Проект Angular 2 на GitHub habrahabr.ru