使用#link-to和动态细分

时间:2018-02-16 12:45:14

标签: ember.js

我有一个简单的应用程序来显示客户列表,以及每个特定客户的详细信息页面。

基本上,有两个网址:

/clients/
/clients/:slug/

我在将Client模型的结果渲染到模板时遇到了一些问题,特别是在使用动态细分的#link-to辅助工具时。

我找到了两种方法,虽然我可以让它们都工作,但我不知道哪一种是最好的,为什么呢。

以下是我的应用程序中的一些(简化)代码。

// app/models/client.js
export default DS.Model.extend({
  name: DS.attr('string'),
  slug: DS.attr('string')
});

(我的实际模型较大,但这些是唯一相关的字段)

这是我的路线:

// app/router.js
Router.map(function() {
  this.route('clients');
  this.route('client', { path: 'clients/:slug' });
});

注意:我没有嵌套路由,因为我不想使用{{outlet}}嵌套模板功能。

这是客户的路线,我在那里检索我的客户列表

// app/routes/clients.js
export default Route.extend({
  model: function() {
    return this.get('store').findAll('client'); // fetch all Clients
  }
});

最后,这是获取单个客户端信息的路径:

// app/routes/client.js
export default Route.extend({
  model: function(params) {
    return this.store.query('client',  {
      filter: { slug: params.slug } // fetch one specific client, by slug
    });
  }
});

到目前为止一切正常,但在模板中显示模型数据时我的问题就开始了。

有两种“方式”,哪一种是正确的?

选项A

//app/templates/clients.hbs
// list all clients using #each
{{#each model as |client|}}
  {{#link-to "client" client}} // pass the "client" object to generate my dynamic routes
    {{client.name}}
  {{/link-to}}
{{/each}}

点击任何生成的链接将呈现客户端详细信息模板client.hbs

//app/templates/client.hbs
<h1>Client - {{model.name}}</h1>

在这个例子中,我可以使用model.name来渲染我的模型对象。那很好,直到我刷新页面!然后,model.name返回的信息被删除。如果我尝试直接访问URL,也是一样的。我必须回到/clients并再次点击该链接以查看我的客户名称。

然后我寻找另一种方式来显示我的数据,其中模型信息将在页面重新加载后继续存在。

选项B:

经过多次阅读后,我发现了一个建议,即使用特定客户端slug / id作为#link-to

的参数
// app/templates/clients.hbs
// list all clients using #each
{{#each model as |client|}}
  {{#link-to "client" client.slug}} // specifically use the actual slug/id, and not the object
    {{client.name}}
  {{/link-to}}
{{/each}}

但是......通过将client.slug而不是client作为参数传递给#link-to,我无法再使用model.name来显示我的数据。它什么都不返回!

//app/templates/client.hbs
<h1>Client - {{model.name}}</h1> <-- model.name now returns nothing D:

然而,由于某种原因,使用循环DOES工作:

//app/templates/client.hbs
{{#each model as |client|}}
  <h1>Client - {{client.name}}</h1> <-- using loop even though I only have one record :(
{{/each}}

因此选项B有效,并且在页面重新加载或从URL直接访问后,信息会正确显示。

但我现在正在使用循环来显示单个记录!我找不到真正有效的替代解决方案。

总结:

选项A 感觉就像是正确的方式,但重新加载页面会消除数据。

选项B 实际上可以正常工作并返回数据,但是我必须使用循环来遍历单个记录,这不会让人觉得惯用/高效。

我非常困惑,任何澄清都会非常感激。

提前致谢!

1 个答案:

答案 0 :(得分:1)

这是有趣的“神奇”事物之一,应该简化入门并使Ember看起来很容易 - 但实际上只是导致路由器最常见的用例最混乱。

至少它现在在指南中。

https://guides.emberjs.com/v2.12.0/routing/specifying-a-routes-model/#toc_dynamic-models

“注意:具有动态段的路径在通过URL输入时将始终调用其模型挂钩。如果通过转换输入路径(例如,使用链接到Handlebars帮助器时)和模型提供了context(link-to的第二个参数),然后不执行钩子。如果提供了一个标识符(例如id或slug),那么将执行模型钩子。“

所以,这是一件事......

但另一件事 - 是你回来了一个数组 - 因为你正在使用查询+过滤器 - 来创建一个数组的记录。

所以,如果你使用queryRecord() - 来获得1条记录 - 那么你就会得到你想要的东西。 :)

我只想补充说{{outlets}}很酷。 Here's我通常如何做到 - 但是我可以看到我的路线总是以这种方式加载所有数据...... /我通常想要的 - 但可以看到在许多情况下如何 - 这是不可取的

而且 - 如果你遇到任何更严重的params问题......调查动态细分中的下划线 - 因为它可能会拖累你。