aurelia
2015年带来了ECMAScript 6规范的最终定稿,并充满了用JavaScript构建现代高级应用程序的信心。
当前JavaScript框架的格局由知名的AngularJS和React主导,它们都以某种方式,形状或形式将其ES6新功能纳入其范式。
但是,还有一个播放器虽然是新颖且相对隐秘的,但在使用现代JavaScript功能时看起来很优雅。 我想花一点时间向您介绍Aurelia 。
奥雷利-谁?
Aurelia是一个下一代框架,它利用ES6,Web组件和模块化等现代概念来帮助您开发高性能,面向未来的应用程序。
Aurelia是Durandal的自然发展, Durandal是由Rob Eisenberg构建的AngularJS竞争对手。 多年来,Aurelia的历史涉及与AngularJS团队的多次 接触 。 因此,AngularJS开发人员可能会对框架的许多方面感到熟悉。
新技术
正如我所说,Aurelia是一个“下一代”框架,因此,它对某些人来说可能是新手。 它运行在Node.js上 ,并使用npm,但它依赖于一些很酷的新技术,我们将在下面简要介绍这些技术:
古尔普
这个不是那么新,但是它是Aurelia设置的核心部分。 我们将使用Gulp将所有文件通过各种任务传递给管道,以确保我们的应用程序都已连接好并准备就绪。
ES6模块装载机Polyfill
ES6模块装载器是原始ES6规范的一部分的System
动态模块装载器的专用输入。 System
加载器正在写入浏览器规范的过程中,但与此同时,此polyfill提供了我们今天可以使用的面向未来的解决方案。
加载程序允许我们使用System.import
方法动态加载 ES6模块语法中定义的模块:
System.import('mymodule').then(function(m) { ... });
除了加载ES6模块之外,加载程序还允许通过使用钩子来加载其他模块语法。
系统JS
凭借其稍微有一些混乱的名字,SystemJS基本上是装载机挂钩的ES6模块加载,使我们能够从NPM,热蒙,ES6模块和加载模块的集合更多 。 您可以将其视为功能丰富的模块加载器,它基于ES6模块加载器Polyfill的面向未来的基础而构建。
jspm
jspm是一个软件包管理器,例如npm,旨在与SystemJS一起使用。 它允许我们从各种来源安装软件包,并将其公开给我们的应用程序,以便我们可以轻松地使用SystemJS导入它们。
让我们开始吧
我假设您已经安装了Node.js,npm和Git,并且您已经熟悉所有这些的用法。
我们将从克隆GitHub的Aurelia示例应用程序存储库开始
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
然后,出于相同的原因在全局安装jspm。
npm install -g jspm
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
现在打开CLI并移至您应用程序的根目录。 完成后,运行命令:
npm install
它将安装我们的依赖项(来自package.json
文件),其中包括:
- Aurelia工具
- Gulp插件
- 测试业力包
该过程完成后,我们还将使用以下命令安装jspm软件包:
jspm install -y
这是实际安装包括Aurelia的模块的位。
最后但并非最不重要的一点,让我们使用jspm安装Bootstrap:
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>
让我们逐步了解<body>
的内容。
如前所述,SystemJS允许我们使用System.import
方法。 在此代码中,我们使用它来导入aurelia-bootsrapper
模块,该模块启动了我们的Aurelia应用程序。 由于运行jspm install -y
时jspm为我们构建的config.js
文件,我们可以按名称引用aurelia-bootstrapper
。 它将模块名称映射到其版本化源。 很漂亮的东西。
System.config
位设置了模块的路径,即从哪里开始查找文件。
现在,创建styles/style.css
文件,并添加以下代码:
body { padding-top: 74px; }
您会注意到,其中包括我们先前安装的Bootstrap。 在阅读本教程时,该版本可能已更改,因此请注意安装了哪个jspm。
aurelia-bootstrapper是做什么的?
aurelia-bootstrapper
模块将扫描index.html
文件中的aurelia-app
属性。 如果此类属性指定了值,则引导程序将使用该名称加载视图/模块; 否则,它将加载一个名为app.html
和app.js
(默认设置)的视图和模块。 视图将被加载到具有aurelia-app
属性的元素(在本例中为<body>
标签)。 它将连接到app.js
文件。
让我们在src
目录中创建一个app.js
和app.html
文件,以查看实际效果:
export class App {
constructor() {
this.name = "Brad";
}
}
<template>
Hello, my name is <strong>${name}</strong>
</template>
您会注意到的第一件事是使用新的ES6模块语法和export
关键字。 您还将注意到使用新的ES6类语法和缩写的函数签名。 由于SystemJS,Aurelia可以直接支持许多令人兴奋的ES6功能。
在这里,我们看到app.js
定义了一个类,其属性公开为变量,供app.html
文件中使用。 该类称为视图模型,因为它是支持我们的视图的数据结构。 我们使用ES6字符串插值语法在模板中打印出变量。
最后一点,我要强调的是,Aurelia中的所有模板都包装在<template>
标记中。
在浏览器中查看我们的应用程序
为了使该应用程序在浏览器中启动并运行,我们需要做的就是执行以下命令:
gulp watch
这将完成编译ES6,实时重新加载等等的所有魔力。 您应该可以在http://localhost:9000/
上看到您的应用程序。 正如我们期望的那样,我们看到了模板内容在<bodygt;
内部呈现<bodygt;
标签,我们看到该属性已插入模板中。
我们的gulpfile
已经为我们设置了BrowserSync,因此如果您进行任何更改,该页面将重新加载。
是时候构建我们的应用程序了
在本节中,我们将构建一个包含两个页面的天真的Reddit客户端:“ Funny”和“ Gifs”。 我们将从Reddit的API中获取每个页面的数据,并在每个页面上显示一个列表。
在构建具有多个页面的任何应用程序时,应用程序的核心是路由器,而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"}
]);
});
}
}
那么,我们在这里做了什么?
第一行( import {Router} from "aurelia_router"
)使用ES6模块导入语法导入路由器本身。
然后,在App
类中,我们有一个称为inject
的静态函数。 熟悉AngularJS的人不仅已经知道依赖注入 。 通过依赖注入, inject
函数将确定在构造函数中可用的参数。 在这种情况下,将提供一个参数,这就是我们的路由器。 您可以看到我们已经更改了构造函数以接受该新参数。
依赖注入功能强大,因为它允许模块之间的松散耦合,并使控制流达到更高的水平,这意味着我们可以在测试期间或稍后更新它们时交换掉这些依赖关系。
现在,我们的类的构造函数中提供了路由器,我们可以使用它来设置路由。
首先,我们使用this.router = router;
将路由器设置为类本身的属性this.router = router;
。 这是Aurelia约定,是路由工作所必需的。 请注意,在这种情况下命名很重要。
其次,我们使用this.router.configure
的回调中提供的config
对象配置路由。 我们设置了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
}
因此,在我们的实例中,我们有两个页面可以在/#/funny
和/#/gifs
,而/#/funny
作为默认页面,这要归功于两个的["", "funny"]
列表路线模式。
我们还需要更新app.html
以用作我们的应用程序的布局文件。
<template>
<a href="/#/funny">Funny</a>
<a href="/#/gifs">Gifs</a>
<router-view>
</router-view>
</template>
您可以看到<router-view></router-view>
自定义元素吗? 这是Aurelia的另一个内置功能。 您可以将其视为AngularJS指令或只是Web组件。 与当前路线关联的视图将自动加载到此元素中。
接下来,我们需要定义两个模块: funny
和gifs
。
编写页面模块
“有趣”模块
我们将从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();
}
}
还要创建/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>
“ 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();
}
}
现在,您应该可以访问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>
结论
好吧,你有它! 您的第一个Aurelia应用程序。 我对Aurelia的未来感到非常兴奋,因为我认为它的简洁明了。 此外,通过使用ES6,它可以将所有内容保留在可重用,可扩展的模块中。 在以后的教程中,我将研究如何抽象Gif和Funny模块之间的重复,以及对Reddit客户端的其他一些改进和补充。 我很想知道您第一次尝试使用Aurelia进行应用程序开发会如何!
我们在本文中构建的完整应用程序可以在这里找到
翻译自: https://www.sitepoint.com/creating-next-generation-javascript-application-aurelia/
aurelia