Ember 中的路由
本文将介绍 **路由**,有时也称为基于 URL 的过滤。我们将使用它为三个待办事项视图(“全部”、“活动”和“已完成”)提供唯一的 URL。
先决条件 |
至少,建议您熟悉核心 HTML、CSS 和 JavaScript 语言,并了解 终端/命令行。 对现代 JavaScript 特性(如类、模块等)的深入了解将非常有益,因为 Ember 大量使用它们。 |
---|---|
目标 | 学习在 Ember 中实现路由。 |
基于 URL 的筛选
Ember 带有一个与浏览器 URL 紧密集成的路由系统。通常,在编写 Web 应用程序时,您希望页面由 URL 表示,这样如果(出于任何原因)页面需要刷新,用户不会对 Web 应用程序的状态感到意外——他们可以链接到应用程序的重要视图。
目前,我们已经有“全部”页面,因为我们目前没有对我们一直使用的页面进行任何过滤,但我们需要对其进行一些重组,以便处理“活动”和“已完成”待办事项的不同视图。
Ember 应用程序有一个默认的“application”路由,它与 app/templates/application.hbs
模板相关联。因为该应用程序模板是我们待办事项应用程序的入口点,所以我们需要进行一些更改以允许路由。
创建路由
让我们从创建三个新的路由开始:“Index”、“Active”和“Completed”。为此,您需要在应用程序的根目录中将以下命令输入到您的终端中
ember generate route index
ember generate route completed
ember generate route active
第二和第三个命令不仅应该生成了新文件,而且还更新了一个现有文件,app/router.js
。它包含以下内容
import EmberRouter from "@ember/routing/router";
import config from "./config/environment";
export default class Router extends EmberRouter {
location = config.locationType;
rootURL = config.rootURL;
}
Router.map(function () {
this.route("completed");
this.route("active");
});
当上面运行第二和第三个命令时,添加了突出显示的行。
router.js
充当开发人员的“站点地图”,以便他们能够快速了解整个应用程序的结构。它还告诉 Ember 如何与您的路由交互,例如在加载任意数据时、在加载数据时处理错误或解释 URL 的动态部分。由于我们的数据是静态的,因此我们不会接触到任何这些花哨的功能,但我们将确保路由提供查看页面所需的最小数据。
创建“Index”路由没有在 router.js
中添加路由定义行,因为与 URL 导航和 JavaScript 模块加载一样,“Index”是一个特殊词,表示要渲染、加载等的默认路由。
为了调整我们渲染 TodoList 应用程序的旧方法,我们首先需要将应用程序模板中的 TodoList 组件调用替换为 {{outlet}}
调用,这意味着“任何子路由将在这里渲染”。
转到 todomvc/app/templates/application.hbs
文件并替换
<TodoList />
与
{{outlet}}
接下来,在我们的 index.hbs
、completed.hbs
和 active.hbs
模板中(也位于模板目录中),我们现在可以只输入 TodoList 组件调用。
在每种情况下,替换
{{outlet}}
与
<TodoList />
因此,如果您现在尝试再次运行应用程序并访问三个路由中的任何一个
localhost:4200 localhost:4200/active localhost:4200/completed
您将看到完全相同的内容。在每个 URL 上,与特定路径(“Active”、“Completed”或“Index”)对应的模板将渲染 <TodoList />
组件。<TodoList />
在页面中渲染的位置由父路由中的 {{ outlet }}
确定,在本例中为 application.hbs
。所以我们已经有了路由。太好了!
但现在我们需要一种方法来区分这些路由,以便它们显示它们应该显示的内容。
首先,再次回到我们的 todo-data.js
文件。它已经包含一个返回所有待办事项的 getter,以及一个返回未完成待办事项的 getter。我们缺少的 getter 是一个仅返回已完成待办事项的 getter。将以下内容添加到现有 getter 下面
get completed() {
return this.todos.filter((todo) => todo.isCompleted);
}
模型
现在我们需要将模型添加到我们的路由 JavaScript 文件中,以便我们可以轻松地返回特定数据集以在这些模型中显示。model
是一个数据加载生命周期钩子。对于 TodoMVC,模型的功能对我们来说并不那么重要;如果您想深入了解,可以在 Ember 模型指南 中找到更多信息。我们还提供了对服务的访问,就像我们对组件所做的那样。
索引路由模型
首先,更新 todomvc/app/routes/index.js
使其如下所示
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
export default class IndexRoute extends Route {
@service("todo-data") todos;
model() {
let todos = this.todos;
return {
get allTodos() {
return todos.all;
},
};
}
}
现在我们可以更新 todomvc/app/templates/index.hbs
文件,以便它包含 <TodoList />
组件时,会显式地使用可用的模型,调用其 allTodos()
getter 以确保显示所有待办事项。
在此文件中,更改
<TodoList />
至
<TodoList @todos={{ @model.allTodos }} />
已完成路由模型
现在更新 todomvc/app/routes/completed.js
使其如下所示
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
export default class CompletedRoute extends Route {
@service("todo-data") todos;
model() {
let todos = this.todos;
return {
get completedTodos() {
return todos.completed;
},
};
}
}
现在我们可以更新 todomvc/app/templates/completed.hbs
文件,以便它包含 <TodoList />
组件时,会显式地使用可用的模型,调用其 completedTodos()
getter 以确保仅显示已完成的待办事项。
在此文件中,更改
<TodoList />
至
<TodoList @todos={{ @model.completedTodos }} />
活动路由模型
最后,对于路由,让我们整理一下我们的活动路由。从更新 todomvc/app/routes/active.js
开始,使其如下所示
import Route from "@ember/routing/route";
import { inject as service } from "@ember/service";
export default class ActiveRoute extends Route {
@service("todo-data") todos;
model() {
let todos = this.todos;
return {
get activeTodos() {
return todos.incomplete;
},
};
}
}
现在我们可以更新 todomvc/app/templates/active.hbs
文件,以便它包含 <TodoList />
组件时,会显式地使用可用的模型,调用其 activeTodos()
getter 以确保仅显示活动(未完成)的待办事项。
在此文件中,更改
<TodoList />
至
<TodoList @todos={{ @model.activeTodos }} />
请注意,在每个路由模型钩子中,我们都返回一个带有 getter 的对象,而不是一个静态对象,或者更多地是静态的待办事项列表(例如,this.todos.completed
)。这样做是为了让模板对待办事项列表有一个动态引用,如果我们直接返回列表,数据将永远不会重新计算,这将导致导航看起来像失败/没有实际过滤。通过在模型数据返回对象中定义一个 getter,待办事项将被重新查找,以便我们对待办事项列表的更改会在渲染的列表中体现出来。
让页脚链接正常工作
因此,我们的路由功能现在都已到位,但我们无法从应用程序中访问它们。让我们使页脚链接处于活动状态,以便单击它们会转到所需的路由。
回到 todomvc/app/components/footer.hbs
,找到以下标记片段
<a href="#">All</a>
<a href="#">Active</a>
<a href="#">Completed</a>
更新为
<LinkTo @route="index">All</LinkTo>
<LinkTo @route="active">Active</LinkTo>
<LinkTo @route="completed">Completed</LinkTo>
<LinkTo>
是一个内置的 Ember 组件,它处理导航路由时所有状态更改,以及在任何与 URL 匹配的链接上设置“active”类,以防需要将其与非活动链接区分开来。
更新 TodoList 中的待办事项显示
我们需要修复的最后一件小事是,以前,在 todomvc/app/components/todo-list.hbs
中,我们直接访问了 todo-data 服务并循环遍历所有待办事项,如下所示
{{#each this.todos.all as |todo| }}
由于我们现在希望 TodoList 组件显示一个过滤后的列表,因此我们希望向 TodoList 组件传递一个参数,该参数代表“当前待办事项列表”,如下所示
{{#each @todos as |todo| }}
本教程到此结束!您的应用程序现在应该在页脚中有完全有效的链接,显示“Index”/默认、“Active”和“Completed”路由。
总结
恭喜!您已完成本教程!
在我们将此处介绍的内容与原始的 TodoMVC 应用程序 相比,还有很多东西要实现,例如编辑、删除和跨页面重新加载持久化待办事项。
要查看我们完成的 Ember 实现,请查看本教程代码的存储库中完成的应用程序文件夹 此处,或查看 实时部署版本。研究代码以了解有关 Ember 的更多信息,并查看下一篇文章,其中提供指向更多资源的链接以及一些故障排除建议。