Создание приложения Next Gen JavaScript с Aurelia

Создание приложения Next Gen JavaScript с Aurelia

815

Создание приложения Next Gen JavaScript с Aurelia
0

 

2015 год принес завершение спецификации ECMAScript 6 и совместно с тем уверенность в создании современных, улучшенных приложений в JavaScript.

JavaScript фреймворки подавлены таковыми гигантами, как AngularJS и React, оба из которых стремятся каким-то образом, либо иной формой, включить новые характеристики ES6 есть в свои парадигмы.

Существует, но, еще один игрок, новый и относительно скрытный, и выглядит элегантно в собственном использовании современных возможностей JavaScript. Я хотел бы представить вам Aurelia.

Aureli-кто?

Aurelia является фреймворком последующего поколения, который использует современные концепты, как ES6, веб-составляющие, и модульность, чтобы помочь вам развить мощные, перспективные приложения.

Aurelia является – естественная прогрессия Durandal, соперника AngularJS, созданная Робом Айзенбергом. История Aurelia включает в себя ряд схваток с командой AngularJS на протяжении почти всех лет. Именно по этой причине многие аспекты фреймворка могут быть знакомы знакомы разрабам AngularJS среди вас.

Новые Технологии

Как я уже произнес, Aurelia – фреймворк “нового поколения” и, как следствие, инструменты, которые он употребляет, могут быть новыми для некоторых из вас. Он работает на Node.js, и употребляет npm, но он опирается на новые интересные технологии, которые мы коротко рассмотрим:

Gulp

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

ES6 Module Loader Polyfill

ES6 Module Loader – это полизаполнение для загрузчика динамического модуля System, который был частью уникальной спецификации ES6. Загрузчик System погрузчик в процессе записи в спецификации браузера, но в то же время это полизаполнение обеспечивает перспективное решение, которое мы можем применять сегодня.

Загрузчик позволяет динамически загружать модули, определенные в модуле синтаксиса ES6 с внедрением метода System.import:


System.import('mymodule').then(function(m) { ... });

1

System.import(‘mymodule’).then(function(m) { … });

В дополнение к загрузке модулей ES6, загрузчик дозволяет загружать другие синтаксисы модуля за счет использования хуков.

SystemJS

SystemJS по существу является коллекцией хуков загрузчика для загрузчика модуля ES6, которые разрешают нам загружать модули из npm, jspm, ES6 модулей и многое другое. Вы сможете считать его многофункциональным загрузчиком модуля, построенном на многообещающем ES6 Module Loader Polyfill.

jspm

jspm – менеджер пакетов, как npm, разработанный для использования с SystemJS. Это дозволяет нам устанавливать пакеты из различных источников и предоставляет их нашему приложению, чтоб мы могли легко импортировать их с SystemJS.

Перейдем к установке

Я предполагаю, что вы уже установили Node.js, npm и Git, и что вы знакомы с внедрением всех из них.

Мы начнем с клонирования репозитория эталона приложения Aurelia из GitHub


git clone https://github.com/aurelia/skeleton-navigation.git

1

git clone https://github.com/aurelia/skeleton-navigation.git

Вы сможете спросить: “Почему мы клонируем образец приложения, а не создаем с нуля свое собственное?”

Причина в том, что Aurelia все еще находится в ранешней стадии, таким образом, еще не существует команды aurelia init, которую вы сможете запустить, чтобы получить файл package.json и все настроить.

Хранилище, которое мы клонировали, выступает в качестве неплохой базы для нашего приложения. Это дает нам структуру каталога, манифест пакета, некие конфигурации тестирования и многое другое. Надеюсь, в один прекрасный день мы будем считаться с таковыми генераторами, как настройки Yeoman. Так как мы используем хранилище для конфигурации, а не для самого эталона приложения, вы можете удалить каталог src/, styles/styles.css и файлы index.html. Мы сделаем наши собственные в ближайшее время.

Нам нужно установить несколько остальных вещей, чтобы установить наши зависимости и начать создавать наше приложение:

Установите gulp глобально, чтоб иметь доступ к gulp CLI:


npm install -g gulp

1

npm install -g gulp

Потом установите jspm глобально по той же причине.


npm install -g jspm

1

npm install -g jspm

Сейчас откройте CLI и перейдите к основному каталогу вашего приложения. После этого, выполните команду:


npm install

1

npm install

Это установит наши зависимости (из файла package.json), которые посреди прочего содержат:

  • инструменты Aurelia
  • плагины Gulp
  • пакеты Karma для тестирования

Опосля того, как процесс будет завершен, мы установим наши jspm пакеты с помощью команды:


jspm install -y

1

jspm install -y

Это устанавливает модули, которые включают в себя Aurelia.

Крайнее, но не менее важное – установка Bootstrap с jspm:


jspm install bootstrap

1

jspm install bootstrap

Стоит отметить, что библиотека Aurelia (содержащаяся в этих модулях) имеет ряд зависимостей, в том числе SystemJS. Все это будет установлено через управление зависимостями в итоге установки Aurelia. Я хотел выделить этот вопрос на вариант, если вам будет интересно, откуда у нас доступ к такому, как SystemJS, невзирая на то, что я не упомянул его здесь, в наших зависимостях.

Пора создавать приложение

Сейчас у нас есть целый ряд инструментов, которые помогут нам сделать приложение. Дальше нам нужна страница index.html:


<!doctype html>
<html>
<head>
<link rel="stylesheet" href="jspm_packages/github/twbs/bootstrap@3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="styles/styles.css">
</head>
<body aurelia-app>
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
System.config({
"paths": {
"*": "dist/*.js"
}
});
System.import('aurelia-bootstrapper');
</script>
</body>
</html>

12345678910111213141516171819

<!doctype html><html>  <head>    <link rel=»stylesheet» href=»jspm_packages/github/twbs/[email protected]/css/bootstrap.min.css»>    <link rel=»stylesheet» href=»styles/styles.css»>  </head>  <body aurelia-app>    <script src=»jspm_packages/system.js»></script>    <script src=»config.js»></script>    <script>      System.config({        «paths»: {          «*»: «dist/*.js»         }      });      System.import(‘aurelia-bootstrapper’);    </script>  </body></html>

Давайте разглядим содержание <body>.

Как я уже упоминал ранее, SystemJS дозволяет использовать метод System.import. В этом коде, мы используем его, чтоб импортировать модуль aurelia-bootsrapper который дает начало нашему приложению Aurelia. Мы можем отыскать aurelia-bootstrapper по названию благодаря файлу config.js, который jspm выстроил для нас, когда мы выполнили команду jspm install -y. Он показывает имя модуля, на версионный источник. Довольно ловко.

System.config настраивает пути для наших модулей, то есть, с чего же начать поиск файлов.

Теперь создайте файл styles/style.css и добавьте этот код к:


body { padding-top: 74px; }

1

body { padding-top: 74px; }

Вы заметите, что у нас будет Bootstrap, который мы установили ранее. Версия может поменяться, поэтому обратите внимание, какой jspm вы установили.

Что делает aurelia-bootstrapper?

Модуль aurelia-bootstrapper просканирует файл index.html для атрибута aurelia-app. Раз такой атрибут определяет значение, то загрузится просмотр/модуль с таковым именем; в противном случае он загрузит просмотр и модуль, который именуется app.html и app.js (по умолчанию). Просмотр загрузится в элемент, у которого есть атрибут aurelia-app (в данном случае тег <body>). Он будет подключен к файлу app.js.

Давайте сделаем файл app.js и app.html в каталоге src, чтобы увидеть это в действии:


export class App {
constructor() {
this.name = "Brad";
}
}

12345

export class App {  constructor() {    this.name = «Brad»;  }}


<template>
Hello, my name is <strong>${name}</strong>
</template>

123

<template>  Hello, my name is <strong>${name}</strong></template>

1-ое, что вы заметите, использование нового синтаксиса модуля ES6 и ключевое слово export. Вы также заметите внедрение нового синтаксиса класса ES6 и сокращенные подписи функций. Aurelia, благодаря SystemJS, поставляется с поддержкой почти всех интересных свойств ES6.

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

В качестве крайнего замечания, я хочу сказать, что все шаблоны в Aurelia добавлены в тег <template>.

Просмотр нашего приложения в браузере

Чтоб приложение работало в браузере, все, что нужно сделать, это выполнить команду:


gulp watch

1

gulp watch

Вы увидите приложение по адресу: http://localhost:9000/. Как мы и ждали, мы видим содержимое нашего шаблона внутри тега <bodygt;, и мы лицезреем свойство, интерполированное в шаблон.

Наш gulpfile уже установил BrowserSync для нас, потому страница перезагрузиться, если вы сделаете какие-либо конфигурации.

Создаем наше приложение

В этом разделе, мы создадим клиент Reddit, у которого две странички: “Funny” и “Gifs”. Мы получим данные для каждой странички из API Reddit и отобразим список на каждой странице.

При разработке любого приложения с несколькими страницами, ядром ​​приложения является рутер и Aurelia ничем не различается. Давайте изменим наш файл app.js, так что он станет главным модулем нашего приложения. Он будет отвечать за определение и опции маршрутизации.


import {Router} from "aurelia-router";

export class App {
static inject() { return [Router]; }

constructor(router) {
this.router = router;
this.router.configure(config => {
config.title = "Reddit";

config.map([
{route: ["", "funny"], moduleId: "funny", nav: true, title: "Funny Subreddit"},
{route: "gifs", moduleId: "gifs", nav: true, title: "Gifs Subreddit"}
]);
});
}
}

1234567891011121314151617

import {Router} from «aurelia-router»; export class App {  static inject() { return [Router]; }   constructor(router) {    this.router = router;    this.router.configure(config => {      config.title = «Reddit»;       config.map([        {route: [«», «funny»], moduleId: «funny», nav: true, title: «Funny Subreddit»},        {route: «gifs», moduleId: «gifs», nav: true, title: «Gifs Subreddit»}      ]);    });  }}

Итак, что же мы сделали?

1-ая строка (import {Router} from “aurelia_router”) импортирует сам рутер, используя ES6 синтаксис импорта модуля.

Потом, в классе App нас есть статическая функция под названием inject. Те из вас, кто знаком с AngularJS и не лишь уже знают о внедрении зависимости. Функция inject определит с помощью внедрения зависимости, какие характеристики будут доступны в нашей функции конструктора. В этом случае, единственный параметр будет обеспечен, и это наш рутер. Вы сможете увидеть, что мы изменили функцию конструктора, чтобы принять новейший параметр.

Теперь, когда у нас есть роутер в конструкторе нашего класса, мы можем применять его для установки рутов.

Прежде всего мы устанавливаем рутер как свойство самого класса с this.router = router;. Это соглашение Aurelia и являются неотклонимыми для работы маршрутизации. Следует отметить, что название принципиально в данном случае.

Во-вторых, мы конфигурируем наши руты с помощью объекта config, предоставленного нам в обратном вызове this.router.configure. Мы устанавливаем свойство title, которое будет применено для названия наших страниц. Мы также передаем перечень определений рута функции config.map.

Каждое определение рута имеет последующую модель:


{
route: ["", "foo"], // Activate this route by default or when on /foo
moduleId: "foo", // When active, load foo.js and foo.html (module)
nav: true, // Add this route to the list of navigable routes (used for building UI)
title: "Foo" // Used in the creation of a pages title
}

123456

{  route: [«», «foo»], // Activate this route by default or when on /foo  moduleId: «foo», // When active, load foo.js and foo.html (module)  nav: true, // Add this route to the list of navigable routes (used for building UI)  title: «Foo» // Used in the creation of a pages title}

Так, в нашем примере мы имеем две странички, которые мы можем посетить в /#/funny и /#/gifs, где /#/funny выступает в качестве нашей страничке по умолчанию, благодаря списку [“”, “funny”] из двух рут моделей.

Мы также должны обновить app.html в качестве файла макета нашего приложения.


<template>
<a href="/#/funny">Funny</a>
<a href="/#/gifs">Gifs</a>
<router-view>
</router-view>
</template>

123456

<template>  <a href=»/#/funny»>Funny</a>  <a href=»/#/gifs»>Gifs</a>  <router-view>  </router-view></template>

Видите пользовательский элемент <router-view></router-view>? Это еще один интегрированная особенность Aurelia. Вы можете воспринимать его как директиву AngularJS либо просто веб-компонент. Просмотр, связанный с текущим рутом автоматом загрузится в этот элемент.

Далее, мы должны определить два модуля: funny и gifs.

Написание модулей странички
Модуль “Funny”

Мы начнем с funny, а затем скопируем его в качестве базы для gifs.

Создайте файл /src/funny.js со следующим содержанием:


import {HttpClient} from 'aurelia-http-client';

export class Funny {
// Dependency inject the HttpClient
static inject() { return [HttpClient]; }

constructor(http) {
this.http = http; // Assign the http client for use later
this.posts = [];
this.subreddit_url = "http://reddit.com/r/funny.json";
}

loadPosts() {
// Aurelia's http client provides us with a jsonp method for
// getting around CORS issues. The second param is the callback
// name which reddit requires to be "jsonp"

return this.http.jsonp(this.subreddit_url, "jsonp").then(r => {
// Assign the list of posts from the json response from reddit
this.posts = r.response.data.children;
});
}

// This is called once when the route activates
activate() {
return this.loadPosts();
}
}

12345678910111213141516171819202122232425262728

import {HttpClient} from ‘aurelia-http-client’; export class Funny {   // Dependency inject the HttpClient  static inject() { return [HttpClient]; }   constructor(http) {    this.http = http; // Assign the http client for use later    this.posts = [];    this.subreddit_url = «http://reddit.com/r/funny.json»;  }   loadPosts() {    // Aurelia’s http client provides us with a jsonp method for    // getting around CORS issues. The second param is the callback    // name which reddit requires to be «jsonp»     return this.http.jsonp(this.subreddit_url, «jsonp»).then(r => {      // Assign the list of posts from the json response from reddit      this.posts = r.response.data.children;    });  }   // This is called once when the route activates  activate() {    return this.loadPosts();  }}

Также сделайте /src/funny.html следующим образом:


<template>
<ul class="list-group">
<li class="list-group-item" repeat.for="p of posts">
<img src.bind="p.data.thumbnail" />
<a href="http://reddit.com${p.data.permalink}">
${p.data.title}
</a>
</li>
</ul>
</template>

12345678910

<template>  <ul class=»list-group»>    <li class=»list-group-item» repeat.for=»p of posts»>      <img src.bind=»p.data.thumbnail» />      <a href=»http://reddit.com${p.data.permalink}»>        ${p.data.title}      </a>    </li>  </ul></template>

Модуль “Gifs”

Давайте просто скопируем наши funny.js и funny.html в src/gifs.js и src/gifs.html соответственно. Нам необходимо немного настроить содержимое gifs.js.


import {HttpClient} from 'aurelia-http-client';

export class Gifs {
static inject() { return [HttpClient]; }

constructor(http) {
this.http = http;
this.posts = [];
this.subreddit_url = "http://reddit.com/r/gifs.json";
}

loadPosts() {
return this.http.jsonp(this.subreddit_url, "jsonp").then(r => {
this.posts = r.response.data.children;
});
}

activate() {
return this.loadPosts();
}
}

123456789101112131415161718192021

import {HttpClient} from ‘aurelia-http-client’; export class Gifs {  static inject() { return [HttpClient]; }   constructor(http) {    this.http = http;    this.posts = [];    this.subreddit_url = «http://reddit.com/r/gifs.json»;  }   loadPosts() {    return this.http.jsonp(this.subreddit_url, «jsonp»).then(r => {      this.posts = r.response.data.children;    });  }   activate() {    return this.loadPosts();  }}

Сейчас вы сможете посетить localhost:9000/#/gifs и увидеть перечень gif постов и их ссылок.

Улучшения в нашем макете

Мы можем сделать пару улучшений в нашем шаблоне макета, использовав рутер Aurelia .

Помните свойство nav:true, которое мы установили в рут конфигурации ранее? Оно добавляет рут в перечень, который мы можем перебирать на наш взгляд, чтоб построить динамическую навигацию. Давайте сделаем это сейчас.

Обновите содержимое app.html последующим образом:


<template>
<div class="container">
<ul class="nav navbar-nav navbar-fixed-top navbar-inverse">
<li repeat.for="navItem of router.navigation" class="${navItem.isActive ? 'active' : ''}">
<a href.bind="navItem.href">
${navItem.title}
</a>
</li>
</ul>

<router-view></router-view>
</div>
</template>

12345678910111213

<template><div class=»container»>  <ul class=»nav navbar-nav navbar-fixed-top navbar-inverse»>    <li repeat.for=»navItem of router.navigation» class=»${navItem.isActive ? ‘active’ : »}»>      <a href.bind=»navItem.href»>        ${navItem.title}      </a>    </li>  </ul>   <router-view></router-view></div> </template>

Вывод

Вот вы и получили свое 1-ое приложение Aurelia. Я представляю будущее Aurelia прямым и ясным. Не считая того, с помощью ES6 модули будут расширяемыми и многоразовыми.

Полное приложение, которое было сотворено в этой статье, можно найти здесь.

www.webdesignmagazine.ru