在 Ember.js 中组织列表、查看、创建和更新路线的最佳实践
Best practice to organize list, view, create and update routes in Ember.js
现在在 ember.js 工作了几年,我仍然不太清楚,什么应该被视为构建列表、查看、创建和更新路由的最佳实践。
到目前为止,我参与的项目主要用于按实体路由树。用于列表的复数实体名称,带有用于创建的子路径,用于详细视图的单数实体名称,带有用于编辑的子路径。例如,post
模型将具有这些路由:/posts
用于列出 posts,/posts/new
用于创建功能,/post/:post_id
用于显示单个 post 和 /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');
}
});
通常我们会 return 来自 posts
路由模型挂钩的 post 的集合,而不是实现 posts.new
路由的模型挂钩(或 return 根据体系结构在那里设置 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
的集合被加载。因为我们不需要这个集合来创建 post 的列表(至少如果我们只在 posts.index
路由而不是所有子路由中显示它们)这感觉不对。
对那些不太熟悉的人的旁注 ember:嵌套路由模型挂钩按顺序执行。所以在我们的例子中,首先是应用程序路由的模型钩子,然后是 posts 路由,然后是 posts.new 路由等待其中一个执行的任何承诺。
那么什么才是最佳实践?
- 如果我们不在嵌套路由中显示 posts,是否应该在
posts.index
路由中获取它们?
- 创建路由不应该嵌套在列表路由下吗?那么我们应该有
posts
、post-new
、post
和 post.edit
路由吗?感觉很混乱,因为 post 相关的代码被分成了三个路由树。这也违背了目前正在开发的 improved file layout 的目标,因为代码将分为三个目录。
- 我们是否应该权衡不必要地获取 posts 的集合,因为大多数用户流来自创建路由之前的这条路由,因此模型挂钩在大多数情况下已经加载了吗?
如果对此有任何想法,我们将不胜感激。决定不在社区闲聊中提出该问题,以便更好地记录答案。
在 ember 中使用 nested route 的要点是将子路由的输出嵌套在父路由中。虽然您当前的结构有效,但它与 ember 具有结构化路由功能的方式并不匹配。
您应该使用具有明确定义的单一嵌套路由 index route。
At every level of nesting (including the top level), Ember
automatically provides a route for the / path named index. To see when
a new level of nesting occurs, check the router, whenever you see a
function, that's a new level.
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 文件,这可以用作您的列表路由。这样做将帮助您避免在转换到创建路由之前获取所有 post 的问题。
虽然与您目前的结构不同,但我建议如下。
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
});
});
根据新建和编辑逻辑的复杂程度,可以考虑将两条路由合二为一,或者在生成空模型后直接将新建转为编辑。
这样做的好处包括:
简单
您不必为所有路线重新定义路径。一切都在 posts/ 下,路线指定下一段。
一致性
JSONapi 模式使用 plural routes 来获取集合和单个对象。
逻辑换行
如果您使用显式 index.js 文件,则可以使用旧的 posts.js 文件作为 post 命名空间中所有项目的通用包装器。 Posts.js 将有一个出口,索引、新建、编辑和查看路线被放入
如果您需要您的视图和编辑路线共享同一代模型,您可以将您的 view/edit 嵌套到一个公共组中,以便它们共享一个父模型。
this.route('posts', function() {
this.route('post', { path: '/:post_id' }, function() {
this.route('view', { path: '/' }) ;
this.route('edit', { path: '/edit' });
})
})
现在在 ember.js 工作了几年,我仍然不太清楚,什么应该被视为构建列表、查看、创建和更新路由的最佳实践。
到目前为止,我参与的项目主要用于按实体路由树。用于列表的复数实体名称,带有用于创建的子路径,用于详细视图的单数实体名称,带有用于编辑的子路径。例如,post
模型将具有这些路由:/posts
用于列出 posts,/posts/new
用于创建功能,/post/:post_id
用于显示单个 post 和 /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');
}
});
通常我们会 return 来自 posts
路由模型挂钩的 post 的集合,而不是实现 posts.new
路由的模型挂钩(或 return 根据体系结构在那里设置 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
的集合被加载。因为我们不需要这个集合来创建 post 的列表(至少如果我们只在 posts.index
路由而不是所有子路由中显示它们)这感觉不对。
对那些不太熟悉的人的旁注 ember:嵌套路由模型挂钩按顺序执行。所以在我们的例子中,首先是应用程序路由的模型钩子,然后是 posts 路由,然后是 posts.new 路由等待其中一个执行的任何承诺。
那么什么才是最佳实践?
- 如果我们不在嵌套路由中显示 posts,是否应该在
posts.index
路由中获取它们? - 创建路由不应该嵌套在列表路由下吗?那么我们应该有
posts
、post-new
、post
和post.edit
路由吗?感觉很混乱,因为 post 相关的代码被分成了三个路由树。这也违背了目前正在开发的 improved file layout 的目标,因为代码将分为三个目录。 - 我们是否应该权衡不必要地获取 posts 的集合,因为大多数用户流来自创建路由之前的这条路由,因此模型挂钩在大多数情况下已经加载了吗?
如果对此有任何想法,我们将不胜感激。决定不在社区闲聊中提出该问题,以便更好地记录答案。
在 ember 中使用 nested route 的要点是将子路由的输出嵌套在父路由中。虽然您当前的结构有效,但它与 ember 具有结构化路由功能的方式并不匹配。
您应该使用具有明确定义的单一嵌套路由 index route。
At every level of nesting (including the top level), Ember automatically provides a route for the / path named index. To see when a new level of nesting occurs, check the router, whenever you see a function, that's a new level.
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 文件,这可以用作您的列表路由。这样做将帮助您避免在转换到创建路由之前获取所有 post 的问题。
虽然与您目前的结构不同,但我建议如下。
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
});
});
根据新建和编辑逻辑的复杂程度,可以考虑将两条路由合二为一,或者在生成空模型后直接将新建转为编辑。
这样做的好处包括:
简单 您不必为所有路线重新定义路径。一切都在 posts/ 下,路线指定下一段。
一致性 JSONapi 模式使用 plural routes 来获取集合和单个对象。
逻辑换行 如果您使用显式 index.js 文件,则可以使用旧的 posts.js 文件作为 post 命名空间中所有项目的通用包装器。 Posts.js 将有一个出口,索引、新建、编辑和查看路线被放入
如果您需要您的视图和编辑路线共享同一代模型,您可以将您的 view/edit 嵌套到一个公共组中,以便它们共享一个父模型。
this.route('posts', function() {
this.route('post', { path: '/:post_id' }, function() {
this.route('view', { path: '/' }) ;
this.route('edit', { path: '/edit' });
})
})