ember.js - 在 Ember.js 中组织列表、查看、创建和更新路由的最佳实践
问题描述
现在使用 ember.js 工作了几年,我仍然不太清楚,什么应该被视为构建列表、查看、创建和更新路由的最佳实践。
到目前为止,我使用的项目主要用于为每个实体路由树。用于列表的复数实体名称与用于创建的子路径和用于详细视图的单数实体名称与用于编辑的子路径。例如,post
模型将具有以下路由:/posts
用于列出帖子、/posts/new
用于创建功能、/post/:post_id
用于显示单个帖子和/post/:post_id/edit
用于编辑该帖子。相应的路由器看起来像这样:
Router.map(function() {
this.route('post', { path: '/post/:post_id' }, function() {
this.route('edit');
});
this.route('posts', function() {
this.route('new');
});
});
这种方法非常适合细节和编辑视图,因为它们共享相同的模型。所以编辑路径的模型钩子可以重用细节视图路径的模型。在 ember 代码中,如下所示:
// app/routes/post.js
import Route from '@ember/routing/route';
export default Route.extend({
model({ post_id }) {
return this.get('store').findRecord('post', post_id);
}
});
// app/routes/post/edit.js
import Route from '@ember/routing/route';
export default Route.extend({
model() {
return this.modelFor('post');
}
});
通常我们会从posts
路由模型钩子返回一组帖子,而不是实现路由模型钩子posts.new
(或者根据架构返回 POJO / Changeset,但这不是这里的问题)。假设我们没有实现posts.new
路由的模型钩子,看起来像:
// app/routes/posts.js
import Route from '@ember/routing/route';
export default Route.extend({
model({ post_id }) {
return this.get('store').findAll('post');
}
});
// app/routes/posts/new.js
import Route from '@ember/routing/route';
export default Route.extend({
});
但是现在这种方法不再有效,因为在加载posts.new
集合之前,向路由的转换被阻塞。posts
因为我们不需要这个集合来创建帖子列表(至少如果我们只在posts.index
路由中而不是在所有子路由中显示它们)这感觉不对。
对那些不熟悉 ember 的人的旁注:嵌套路由模型钩子按顺序执行。所以在我们的例子中,首先是应用程序路由的模型钩子,然后是发布路由,然后是 post.new 路由等待其中一个执行的任何承诺。
那么什么应该被视为最佳实践呢?
posts.index
如果我们不在嵌套路由上显示帖子,是否应该在路由中获取帖子?- 创建路由不应该嵌套在列表路由下吗?那么我们应该有
posts
,post-new
,post
和post.edit
路线吗?感觉很混乱,因为帖子相关的代码被分成了三个路由树。这也违背了当前正在开发的改进文件布局的目标,因为代码将被拆分为三个目录。 - 我们是否应该权衡不必要地获取帖子集合,因为大多数用户流在创建路由之前来自此路由,因此模型挂钩在大多数情况下无论如何都已经加载?
对此有任何想法将不胜感激。决定不在社区 slack 中问这个问题,以更好地记录答案。
解决方案
在 ember 中嵌套路由的要点是将子路由的输出嵌套在父路由中。虽然您当前的结构有效,但它与 ember 的结构化路由功能并不匹配。
您应该使用带有明确定义的索引路由的单一嵌套路由。
在每一层嵌套(包括顶层),Ember 自动为 / 路径命名的 index 提供一个路由。要查看何时出现新的嵌套级别,请检查路由器,每当您看到一个函数时,这就是一个新的级别。
Router.map(function() {
this.route('posts', function() {
this.route('favorites');
});
});
相当于
Router.map(function() {
this.route('index', { path: '/' });
this.route('posts', function() {
this.route('index', { path: '/' });
this.route('favorites');
});
});
如果你创建一个明确的 posts/index.js 文件,它可以用作你的列表路由。这样做将帮助您避免在转换到创建路由之前获取所有帖子的问题。
虽然与您目前拥有的结构不同,但我建议以下内容。
Router.map(function() {
this.route('posts', function() {
this.route('index'); // /posts - posts/index.js
this.route('new'); // /posts/new - posts/new.js
this.route('view', { path: '/:post_id' } // /posts/1234 - posts/view.js
this.route('edit', { path: '/:post_id/edit' } // /posts/1234/edit - posts/edit.js
});
});
根据new和edit中逻辑的复杂程度,可以考虑将两条路由合二为一,或者在生成空模型后简单的将new转为edit。
这样做的好处包括:
简单性 您不必为所有路线重新定义路径。一切都属于posts/,并且路线指定了下一块。
一致性 JSONapi 模式使用复数路由来获取集合和单个对象。
逻辑包装 如果您使用显式 index.js 文件,则可以使用旧的 posts.js 文件作为 post 命名空间内所有项目的通用包装器。Posts.js 将有一个插座,用于放置索引、新建、编辑和查看路由
如果您需要您的视图和编辑路线来共享相同的模型生成,您可以将您的视图/编辑嵌套到一个公共组中,以便它们共享一个父模型。
this.route('posts', function() {
this.route('post', { path: '/:post_id' }, function() {
this.route('view', { path: '/' }) ;
this.route('edit', { path: '/edit' });
})
})
推荐阅读
- excel - 有没有办法在excel的单元格中编码结果列表
- python - 我的应用程序容器无法访问我的 mysql 容器
- mysql - 如何在 Sequelize ORM for express.js 中比较区分大小写的字符串数据?
- java - Spring 重试 Rest Template 重试模板功能
- ios - iOS 访问存储在 Google 云存储桶中的图像
- generics - 如何将可变参数转换为列表?
- php - 使用php从rgba css代码中删除不透明度
- c++ - 如何在 Linux 中使用 exec 函数族执行 a.out 文件
- ruby-on-rails - 在 AWS 上复制 Heroku 的评论应用程序
- c# - 我可以在 Task.WaitAll 之后使用 task.Result