ember js搭建web
Ember.js是一个自以为是的前端JavaScript框架,近来引起了人们的极大兴趣。 本文将介绍该框架的一些关键概念,同时使用该框架构建一个简单的应用程序,以显示其功能的基本示例。
我们的示例应用程序将是“骰子滚子”,包括掷骰子和查看迄今为止已执行的所有骰子掷骰历史的功能。 可以从Github获得此应用程序的完整版本
Ember.js框架将许多现代JavaScript概念和技术整合到一个包中,包括但不限于:
- 使用Babel编译器工具来全面支持ES2016。
- 由Testem和QTest提供标准的单元,集成和验收级别的测试支持。
- 使用Broccoli.js建立资产。
- 支持实时重载,缩短了开发周期。
- 使用Handlebars标记语法进行模板化。
- URL路由的最初开发是确保整个过程都完全支持深层链接。
- 围绕JSON API构建的完整数据层,但是可插入所需的任何API访问。
为了使用Ember.js,假定您已经安装了Node.js和npm的最新版本。 如果没有,则可以从Node.js网站下载并安装。
还应该提到Ember纯粹是一个前端框架。 它具有多种与您选择的后端进行交互的方式,但是Ember本身并未以任何方式处理此后端。
介绍ember-cli
Ember.js的许多功能都来自其命令行界面(CLI)。 这个工具-称为ember-cli-为Ember.js应用程序的大部分开发生命周期提供动力,从创建应用程序开始,一直向其中添加功能,直到运行测试套件,然后以开发模式启动实际项目。
在开发Ember.js应用程序时,您所做的几乎所有工作都会在某种程度上涉及此工具,因此了解如何最佳使用它很重要。 我们将在本文全文中使用它。
我们需要做的第一件事是确保正确安装了Ember.js CLI并保持最新状态。 这是通过从npm安装来完成的,如下所示:
$ npm install -g ember-cli
我们可以通过运行以下命令来检查它是否已成功安装:
$ ember --version
ember-cli: 2.15.0-beta.1
node: 8.2.1
os: darwin x64
创建您的第一个Ember.js应用
安装ember-cli后,就可以开始创建应用程序了。 这是我们将首先使用Ember.js CLI工具的地方-它创建了整个应用程序结构,将所有内容设置为可以运行。
$ ember new dice-roller
installing app
create .editorconfig
create .ember-cli
create .eslintrc.js
create .travis.yml
create .watchmanconfig
create README.md
create app/app.js
create app/components/.gitkeep
create app/controllers/.gitkeep
create app/helpers/.gitkeep
create app/index.html
create app/models/.gitkeep
create app/resolver.js
create app/router.js
create app/routes/.gitkeep
create app/styles/app.css
create app/templates/application.hbs
create app/templates/components/.gitkeep
create config/environment.js
create config/targets.js
create ember-cli-build.js
create .gitignore
create package.json
create public/crossdomain.xml
create public/robots.txt
create testem.js
create tests/.eslintrc.js
create tests/helpers/destroy-app.js
create tests/helpers/module-for-acceptance.js
create tests/helpers/resolver.js
create tests/helpers/start-app.js
create tests/index.html
create tests/integration/.gitkeep
create tests/test-helper.js
create tests/unit/.gitkeep
create vendor/.gitkeep
NPM: Installed dependencies
Successfully initialized git.
$
这导致创建了可以运行的整个应用程序。 它甚至将Git设置为源代码控制来跟踪您的工作。
注意:如果愿意,可以禁用Git集成,并且可以优先选择Yarn而不是npm。 该工具的帮助对此进行了介绍。
现在,让我们看看它的外观。 再次出于开发目的启动Ember应用程序,也可以使用ember-cli完成:
$ cd dice-roller
$ ember serve
Livereload server on http://localhost:49153
'instrument' is imported from external module 'ember-data/-debug' but never used
Warning: ignoring input sourcemap for vendor/ember/ember.debug.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-2fXNPqjl.tmp/vendor/ember/ember.debug.map'
Warning: ignoring input sourcemap for vendor/ember/ember-testing.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-Xwpjztar.tmp/vendor/ember/ember-testing.map'
Build successful (5835ms) – Serving on http://localhost:4200/
Slowest Nodes (totalTime => 5% ) | Total (avg)
----------------------------------------------+---------------------
Babel (16) | 4625ms (289 ms)
Rollup (1) | 445ms
我们现在准备出发。 该应用程序在http:// localhost:4200上运行,如下所示:
它还正在运行LiveReload服务,该服务会自动监视文件系统的更改。 这意味着您在调整站点设计时可以有非常快的周转时间。
试试吧?
初始页面已经告诉我们该怎么做,所以让我们去更改主页,看看会发生什么。 我们将更改app/templates/application.hbs
文件,使其类似于以下内容。
This is my new application.
{{outlet}}
注意:
{{outlet}}
标签是Ember中“路由”工作方式的一部分。 我们将在稍后介绍。
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
首先要注意的是ember-cli的输出,如下所示:
file changed templates/application.hbs
Build successful (67ms) – Serving on http://localhost:4200/
Slowest Nodes (totalTime => 5% ) | Total (avg)
----------------------------------------------+---------------------
SourceMapConcat: Concat: App (1) | 9ms
SourceMapConcat: Concat: Vendor /asset... (1) | 8ms
SimpleConcatConcat: Concat: Vendor Sty... (1) | 4ms
Funnel (7) | 4ms (0 ms)
这告诉我们,已经发现我们更改了模板,并重新构建并重新启动了所有内容。 在这部分中,我们的参与为零。
现在让我们看一下浏览器。 如果您已安装并运行LiveReload,则甚至无需刷新浏览器就可以启动该浏览器,否则,您将需要重新加载当前页面。
并不是很令人兴奋,但这是我们几乎不费吹灰之力实现的。
此外,我们还提供了一个完整的测试套件,可以运行。 毫不奇怪,这也是使用Ember工具运行的,如下所示:
$ ember test
⠸ Building'instrument' is imported from external module 'ember-data/-debug' but never used
⠴ BuildingWarning: ignoring input sourcemap for vendor/ember/ember.debug.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-S8aQFGaz.tmp/vendor/ember/ember.debug.map'
⠇ BuildingWarning: ignoring input sourcemap for vendor/ember/ember-testing.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-wO8OLEE2.tmp/vendor/ember/ember-testing.map'
cleaning up...
Built project successfully. Stored in "/Users/coxg/source/me/writing/repos/dice-roller/tmp/class-tests_dist-PUnMT5zL.tmp".
ok 1 PhantomJS 2.1 - ESLint | app: app.js
ok 2 PhantomJS 2.1 - ESLint | app: resolver.js
ok 3 PhantomJS 2.1 - ESLint | app: router.js
ok 4 PhantomJS 2.1 - ESLint | tests: helpers/destroy-app.js
ok 5 PhantomJS 2.1 - ESLint | tests: helpers/module-for-acceptance.js
ok 6 PhantomJS 2.1 - ESLint | tests: helpers/resolver.js
ok 7 PhantomJS 2.1 - ESLint | tests: helpers/start-app.js
ok 8 PhantomJS 2.1 - ESLint | tests: test-helper.js
1..8
# tests 8
# pass 8
# skip 0
# fail 0
# ok
注意,输出讨论了PhantomJS 。 这是因为完全支持在浏览器中运行的集成测试,并且默认情况下,这些测试在PhantomJS浏览器中无头运行。 如果您愿意,可以在其他浏览器中完全运行它们,并且在设置持续集成(CI)时值得这样做,以确保您的应用程序在所有受支持的浏览器中都能正常运行。
Ember.js应用程序的结构
在实际编写应用程序之前,让我们探讨一下文件系统上的结构。 上面的ember new
命令将在您的计算机上创建一个完整的目录结构,其中包含许多不同的部分。 了解所有这些对于有效使用该工具并创建出色的项目很重要。
在最顶层,您会注意到以下文件和目录:
- README.md –这是描述应用程序的标准自述文件
- package.json –这是描述应用程序的标准npm配置文件。 这主要用于正确安装依赖项。
- ember-cli-build.js –这是Ember CLI工具的配置,可为构建提供动力
- testem.js –这是测试框架的配置。 这使您可以定义用于在不同环境中运行测试的浏览器。
- app / –这是实际的应用程序逻辑。 这里发生了很多事情,下面将进行介绍。
- config / –这是应用程序的配置
- config / targets.js –这是要支持的浏览器列表。 Babel使用它来确保对Javascript进行编译,以使它们都能正常工作。
- config / environment.js –这是您的应用程序的主要配置。 应用程序所需的任何内容,但可能因一个环境而异,都应放在此处。
- public / –这是您希望包含在应用程序中的任何静态资源。 例如,图像和字体。
- 供应商/ –这是构建系统未管理的任何前端依赖项
- 测试/ –这是所有测试的去向
- 测试/单元 –这是应用程序的所有单元测试
- 测试/集成 –这是应用程序的所有集成测试
总体页面结构(包括第三方内容)
在我们取得进展之前,让我们为页面提供某种形式的结构。 在这种情况下,我们将添加Materialize CSS框架以使其外观更好。
可以通过多种方式添加对第三方内容的支持,例如:
- 直接链接到CDN等外部服务上的内容
- 使用npm或Bower之类的软件包管理器为我们安装它
- 将其直接包含在我们的应用程序中。
- 如果提供了Ember Addon,请使用
不幸的是,Materialize的插件尚不能与最新版本的Ember.js一起使用,因此,我们只是要从我们的主页链接到CDN资源。 为了实现此目的,我们将更新app/index.html
,这是将应用程序呈现到其中的主页结构。 我们将仅添加jQuery,Google图标字体和Materialize的CDN链接。
<!-- Inside the Head section -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.1/css/materialize.min.css">
<!-- Inside the Body section -->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.1/js/materialize.min.js"></script>
现在,我们可以更新主页以显示我们的核心模板。 这是通过编辑app/templates/application.hbs
来完成的,如下所示:
<nav>
<div class="nav-wrapper">
<a href="#" class="brand-logo">
<i class="material-icons">filter_6</i>
Dice Roller
</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
</ul>
</div>
</nav>
<div class="container">
{{outlet}}
</div>
这在屏幕顶部为我们提供了Materialize Nav,并带有一个容器,其中包含前面提到的{{outlet}}
标签。
在浏览器中访问时,它看起来像这样:
那么,这个outlet
标签是什么? 灰烬基于路线而工作,其中每个路线都被视为其他路线的子级。 最顶层的路由由Ember自动处理,并呈现模板app/templates/application.hbs
。
outlet
标签指定Ember将在当前层次结构中呈现下一个路由的位置–从而将第一级路由呈现到application.hbs
该标签中,将第二级路由呈现到该第一级模板中的该标签中,依此类推。
创建一条新路线
在Ember.js应用程序中,可以通过路由访问每个可以访问的页面。 浏览器打开的URL和应用程序呈现的路由之间存在直接映射。
最简单的方法是通过示例。 让我们向应用程序添加一条新路线,允许用户实际掷骰子。 再一次,这是使用ember-cli工具完成的。
$ ember generate route roll
installing route
create app/routes/roll.js
create app/templates/roll.hbs
updating router
add route roll
installing route-test
create tests/unit/routes/roll-test.js
这一条命令给我们的是:
- 路线处理程序–
app/routes/roll.js
- 路线
app/templates/roll.hbs
–app/templates/roll.hbs
- 路线
tests/unit/routes/roll-test.js
–tests/unit/routes/roll-test.js
- 更新了路由器配置以了解此新路由–
app/router.js
让我们看看实际情况。 现在,我们将有一个非常简单的页面,允许我们掷出许多骰子。 为此,请如下更新app/templates/roll.hbs
:
<div class="row">
<form class="col s12">
<div class="row">
<div class="input-field col s12">
<input placeholder="Name" id="roll_name" type="text" class="validate">
<label for="roll_name">Name of Roll</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input placeholder="Number of dice" id="number_of_dice" type="number" class="validate" value="1">
<label for="number_of_dice">Number of Dice</label>
</div>
<div class="input-field col s6">
<input placeholder="Number of sides" id="number_of_sides" type="number" class="validate" value="6">
<label for="number_of_sides">Number of Sides</label>
</div>
</div>
<div class="row">
<button class="btn waves-effect waves-light" type="submit" name="action">
Roll Dice
<i class="material-icons right">send</i>
</button>
</div>
</form>
</div>
{{outlet}}
然后访问http:// localhost:4200 / roll并查看结果:
现在我们需要能够到达这里。 Ember通过使用link-to
标签使实现起来非常简单。 这将(除其他事项外)使用我们将用户发送到的路线的名称,然后呈现标记以将用户带到那里。
对于我们的情况,我们将更新app/templates/application.hbs
以包含以下内容:
<ul id="nav-mobile" class="right hide-on-med-and-down">
{{#link-to 'roll' tagName="li"}}
<a href="roll">Roll Dice</a>
{{/link-to}}
</ul>
这使得标题栏如下所示:
然后,这个新链接会将用户带到我们刚刚设置的“ / roll”路线,完全符合您的期望。
创建模块化组件
到目前为止,如果您实际测试了该应用程序,您将注意到一个问题。 打开主页并访问“ / roll”链接有效,但表单上的标签未正确对齐。 这是因为Materialize需要触发一些JavaScript来进行处理,但是动态路由意味着不会重新加载该页面。 我们将需要在这里提供一些帮助。
输入组件。 组件是具有完整生命周期并可以进行交互的UI。 如果需要,它们也是创建可重用UI元素的方式-我们将在以后看到。
现在,我们将创建一个代表Roll Dice表单的组件。 与往常一样,使用我们的ember-cli工具完成组件的生成,如下所示:
$ ember generate component roll-dice
installing component
create app/components/roll-dice.js
create app/templates/components/roll-dice.hbs
installing component-test
create tests/integration/components/roll-dice-test.js
这给了我们:
- app / components / roll-dice.js –为组件提供动力的代码
- app / templates / components / roll-dice.hbs –控制外观的模板
- tests / integration / components / roll-dice-test.js –确保组件正常工作的测试
现在,我们将所有标记移到组件中-这不会对应用程序直接运行的方式产生任何影响,但使我们可以轻松地做到这一点。
更新app/templates/components/roll-dice.hbs
如下:
<form class="col s12">
<div class="row">
<div class="input-field col s12">
<input placeholder="Name" id="roll_name" type="text" class="validate">
<label for="roll_name">Name of Roll</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input placeholder="Number of dice" id="number_of_dice" type="number" class="validate" value="1">
<label for="number_of_dice">Number of Dice</label>
</div>
<div class="input-field col s6">
<input placeholder="Number of sides" id="number_of_sides" type="number" class="validate" value="6">
<label for="number_of_sides">Number of Sides</label>
</div>
</div>
<div class="row">
<button class="btn waves-effect waves-light" type="submit" name="action">
Roll Dice
<i class="material-icons right">send</i>
</button>
</div>
</form>
然后如下更新app / templates / roll.hbs:
<div class="row">
{{roll-dice}}
</div>
{{outlet}}
我们组件的模板正是我们之前在路线中使用的标记,并且现在我们的路线已经大大简化了。 roll-dice
标签告诉Ember在正确的位置渲染组件。
如果现在运行它,我们将看不到任何功能上的区别,但是这种方式使我们的代码更加模块化。 我们将利用该组件来修复渲染故障并为我们的系统添加一些功能。
组件生命周期
余烬组件具有定义的生命周期,并且具有许多可以在不同阶段触发的挂钩。 我们将使用didRender
钩子(在第一次或之后的任何时间渲染组件后调用),以要求Materialize更新文本字段上的标签。
这是通过更新组件背后的代码(位于app/components/roll-dice.js
)来app/components/roll-dice.js
,如下所示:
/* global Materialize:false */
import Ember from 'ember';
export default Ember.Component.extend({
didRender() {
Materialize.updateTextFields();
}
});
现在,每次您访问“ / roll”路线时(无论是通过深度链接还是通过我们的标题链接),都会运行此代码,Materialize将更新标签以使其正确流动。
数据绑定
我们还希望能够通过我们的组件将数据传入和传出UI。 这非常容易实现,但是令人惊讶的是,Ember指南没有涵盖它,因此看起来比应该的要难。
我们想要与之交互的每条数据都存在于Component类中,因为它是自己的字段。 然后,我们使用一些帮助器将输入字段呈现在组件上,以完成将这些输入字段绑定到组件变量的工作,从而使我们可以直接与它们交互,而无需关心DOM活动。
在这种情况下,我们有三个字段,因此我们需要在组件定义内的app/components/roll-dice.js
添加以下三行:
rollName: '',
numberOfDice: 1,
numberOfSides: 6,
然后,我们将模板更新为使用助手进行渲染,而不是直接渲染HTML标记。 为此,请按如下所示替换<input>
标记:
<div class="row">
<div class="input-field col s12">
<!-- This replaces the <input> tag for "roll_name" -->
{{input placeholder="Name" id="roll_name" class="validate" value=(mut rollName)}}
<label for="roll_name">Name of Roll</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<!-- This replaces the <input> tag for "number_of_dice" -->
{{input placeholder="Number of dice" id="number_of_dice" type="number" class="validate" value=(mut numberOfDice)}}
<label for="number_of_dice">Number of Dice</label>
</div>
<div class="input-field col s6">
<!-- This replaces the <input> tag for "number_of_sides" -->
{{input placeholder="Number of sides" id="number_of_sides" type="number" class="validate" value=(mut numberOfSides)}}
<label for="number_of_sides">Number of Sides</label>
</div>
</div>
请注意, value
属性的语法有点奇怪。 此语法可用于标记上的任何属性,而不仅限于value
。 可以使用三种方法:
- 作为带引号的字符串–该值按原样使用
- 作为无引号的字符串–值是从组件上的这条数据中填充的,但是组件永远不会更新
- 如
(mut <name>)
-值从这块数据的部件上填充,并且当该值在浏览器改变所述分量的mut ated
上面所有这些都意味着我们现在可以访问在组件中定义的这三个字段,就好像它们是输入框的值一样,Ember确保一切正常工作。
组件动作
我们要做的下一件事是与组件交互。 具体来说,单击“滚动骰子”按钮时最好进行处理。 Ember通过Actions来处理这个问题-Actions是组件中的代码段,可以将它们连接到模板中。 动作简单地定义为组件类中的函数,在一个称为actions
的特殊字段内,该函数实现我们所需的功能。
现在,我们仅要告诉用户他们想做什么,但实际上不做任何事情–接下来就是。 这将对表单本身使用“提交时”操作,这意味着如果他们单击按钮或在其中一个字段中按Enter,就会触发该操作。
app/components/roll-dice.hbs
内部的动作代码块如下所示:
actions: {
triggerRoll() {
alert(`Rolling ${this.numberOfDice}D${this.numberOfSides} as "${this.rollName}"`);
return false;
}
}
我们返回false
以防止事件冒泡 。 这是HTML应用程序中的相当标准的行为,在这种情况下,这是阻止表单提交重新加载页面所必需的。
您将注意到,我们引用了我们先前定义的用于访问输入字段的字段。 这里根本没有DOM访问权限,而只是与JavaScript变量进行交互。
现在我们只需要进行连接。 在我们的模板中,我们需要告诉表单标记,当触发onsubmit
事件时,它需要触发此动作。 这只是使用Ember帮助器将单个属性添加到form标签,以将其关联到我们的操作。 在app/templates/components/roll-dice.hbs
看起来如下:
<form class="col s12" onsubmit={{action 'triggerRoll'}}>
现在,我们可以单击按钮,填写完表格,然后弹出一个弹出窗口,告诉我们我们已经完成了什么。
在客户端和服务器之间管理数据
我们接下来要做的实际上是掷骰子。 这将涉及与服务器的一些通信-因为服务器负责掷骰子并记住结果。
我们期望的流程是:
- 用户指定他们希望掷出的骰子
- 用户按下“滚骰子”按钮
- 浏览器将详细信息发送到服务器
- 服务器掷骰子,记住结果,并将结果发送回客户端
- 浏览器显示掷骰子的结果
听起来很简单。 而且,当然,对于Ember来说确实如此。
Ember通过使用模型填充的商店的内置概念来处理此问题。 商店是整个应用程序中唯一的知识来源,每个模型都是商店中的一条信息。 所有模型都知道如何将自己持久化到后端,而商店也知道如何创建和访问模型。
将控制权从零部件传递到路线
在整个应用程序中,确保封装正确无误非常重要。 路线(以及我们未介绍的控制器)可以访问商店。 组件没有。
这是因为路由表示应用程序中的特定功能,而组件表示一小部分UI。 为了解决这个问题,组件可以在层次结构中向上发送一个信号,表明已经发生了某些动作–以非常相似的方式,我们的DOM组件可以向我们的组件发出信号,表明发生了某些事情。
首先,让我们将显示警报框的逻辑转移到路径中,而不是组件中。 为此,我们需要更改以下代码区域:
在路线背后的逻辑( app/routes/roll.js
,我们需要添加以下代码块来注册我们将要执行的动作。
actions: {
saveRoll: function(rollName, numberOfDice, numberOfSides) {
alert(`Rolling ${numberOfDice}D${numberOfSides} as "${rollName}"`);
}
}
在组件背后的逻辑( app/components/roll-dice.js
,我们需要在触发自身时触发对组件的操作。 这是通过我们预先存在的动作处理程序中的sendAction
机制完成的。
triggerRoll() {
this.sendAction('roll', this.rollName, this.numberOfDice, this.numberOfSides);
return false;
}
最后,我们需要采取行动。 这是在路线模板– app/templates/roll.hbs
–中完成的,方法是更改组件的呈现方式:
{{roll-dice roll="saveRoll" }}
这告诉组件属性roll
链接到我们路线内的动作saveRoll
。 然后在我们的组件内部使用此名称roll
,以向调用者指示已完成骰子滚动。 这个名称对我们的组件有意义-因为它知道它正在请求执行骰子掷骰,但是并不关心其他代码如何执行或将如何处理信息。
同样,运行此命令不会对我们的应用程序造成功能上的差异,而只是意味着各个部分都位于正确的位置。
坚持到商店
在我们能够将数据持久存储到存储中之前,我们需要定义一个模型来表示它。 这是通过再次使用我们可靠的ember-cli工具来创建该结构,然后填充它来完成的。
要创建模型类,我们执行:
$ ember generate model roll
installing model
create app/models/roll.js
installing model-test
create tests/unit/models/roll-test.js
然后,我们告诉模型需要了解的属性。 这是通过修改app/models/roll.js
使其类似于以下内容来完成的:
import DS from 'ember-data';
export default DS.Model.extend({
rollName: DS.attr('string'),
numberOfDice: DS.attr('number'),
numberOfSides: DS.attr('number'),
result: DS.attr('number')
});
DS.attr
调用定义了指定类型的新属性-在Ember中称为Transform。 此处的默认选项为“字符串”,“数字”,“日期”和“布尔值”,不过您可以根据需要定义自己的选项。
现在我们可以实际使用它来创建或滚动。 这是通过从我们现在在app/routes/roll.js
操作访问商店来完成的:
saveRoll: function(rollName, numberOfDice, numberOfSides) {
let result = 0;
for (let i = 0; i < numberOfDice; ++i) {
result += 1 + (parseInt(Math.random() * numberOfSides));
}
const store = this.get('store');
// This requests that the store give us an instance of our "roll" model with the given data
const roll = store.createRecord('roll', {
rollName,
numberOfDice,
numberOfSides,
result
});
// This tells our model to save itself to our backend
roll.save();
}
如果我们尝试一下,现在我们将看到按下Roll Dice按钮会导致对我们的服务器进行网络呼叫。 这失败了,因为我们的服务器尚未期望它,但是它正在进步。
我们不在这里关注后端,因此我们将对此进行关注。 如果您需要开发一个完全没有后端的Ember应用程序,那么可以使用一些选项-例如ember-localstorage-adapter ,它们将完全在浏览器中运行。 另外,您只需要编写适当的服务器,并确保正确托管了服务器和客户端,即可正常工作。
从商店加载
现在我们已经将一些数据存储到存储中,我们需要再次将其取回。 同时,我们将编写一个索引路由,即您访问主页时使用的索引路由。
Ember隐式具有称为index
的路由,该路由用于呈现应用程序的初始页面。 如果此路由的文件不存在,则不会引发任何错误,而是不呈现任何内容。 我们将使用此路线来渲染商店中的所有历史记录。
因为索引路由已经隐式存在,所以不需要使用ember-cli工具-我们可以直接创建文件,并且已经连接好了。
我们的路由处理程序将进入app/routes/index.js
,如下所示:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.get('store').findAll('roll');
}
});
在这里,我们的路线可以直接访问商店,并且可以使用findAll
方法来加载已findAll
每个滚动。 然后,我们使用model
方法将它们提供给模板。
然后,我们的模板将进入app/templates/index.hbs
,如下所示:
<table>
<thead>
<tr>
<th>Name</th>
<th>Dice Rolled</th>
<th>Result</th>
</tr>
</thead>
<tbody>
{{#each model as |roll|}}
<tr>
<td>{{roll.rollName}}</td>
<td>{{roll.numberOfDice}}D{{roll.numberOfSides}}</td>
<td>{{roll.result}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{outlet}}
这样可以直接从路由访问模型,然后对其进行迭代以生成表行。 然后将如下所示:
摘要
此时,经过相对较少的工作,我们开发了一个应用程序,该应用程序允许我们掷骰子并查看所有掷骰的历史。 这包括从表单中进行数据绑定,将数据持久存储到存储中以及将其读回,模板支持显示所有页面以及整个URL路由。 此应用程序可以在一个小时内从头开始开发。
使用Ember可以大大提高开发前端的效率。 与React等库不同,Ember为您提供了构建功能全面的应用程序所需的整套功能,而无需任何额外的工具。 然后,添加ember-cli
和开箱即用的设置会将其提升到一个新的水平,从而使该过程从头到尾都非常简单和轻松。 加上社区的支持 ,几乎没有什么是无法实现的。
不幸的是,将Ember放入现有项目可能很困难。 在开始新项目时,它效果最佳。 将其安装到现有的中可能是困难的或不可能的。 Ember还可以使用非常特定的后端处理方式来进行开箱即用,如果您现有的后端不符合此要求,那么您可能会花费大量时间和精力重新处理后端或查找/编写插件与现有的交谈。
Ember具有强大的功能,可以让您非常快速地创建功能齐全的应用程序前端。 它确实在如何设计代码方面强加了很多结构,但是,这种限制通常比最初看起来的要少,因为无论如何该结构都是必需的。
翻译自: https://www.sitepoint.com/ember-js-perfect-framework-web-applications/
ember js搭建web