You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:在Ember中通过查询参数实现JSONAPI过滤器的最优方案

问题:Ember路由中JSONAPI风格的数组类型查询参数无法正确传递

昨天我花了好长时间尝试在Ember应用的查询参数里加入符合JSONAPI规范的filter。用Ember Data给端点传filter数组倒是挺简单,但麻烦的是特定路由的查询参数里没法正确反映这个filter数组——其他非数组类型的查询参数都正常工作,就这个数组型的不行。

TL;DR:试了好几种方法都没搞定,现有的解决方案不够DRY(Don't Repeat Yourself),用起来体验太差。我觉得肯定有其他开发者已经解决过这个问题,找到了更优雅的方案,下面是我目前的尝试细节:

最初的尝试(参考Ember官方文档)

我照着Ember查询参数的官方文档写了下面的代码:

Controller代码

import Controller from '@ember/controller';
export default Controller.extend({
  queryParams: ['sort', 'filter'],
  sort: 'id',
  init() {
    this._super(...arguments);
    this.set('filter', []);
  },
});

Route代码

import Route from '@ember/routing/route';
export default Route.extend({
  queryParams: {
    filter: { refreshModel: true },
    sort: { refreshModel: true }
  },
  model(params) {
    console.log(JSON.stringify(params)); // filter始终是[]
    return this.get('store').query('contact', params);
  }
});

验收测试代码

(这是用来验证概念的测试,之后会扩展更复杂的逻辑)

test('visiting /contacts with query params', async function(assert) {
  assert.expect(1);
  let done = assert.async();
  server.createList('contact', 10);
  server.get('/contacts', (schema, request) => {
    let params = request.queryParams;
    assert.deepEqual(
      params,
      { sort: '-id', "filter[firstname]": 'wibble' },
      'Query parameters are passed in as expected'
    );
    done();
    return schema.contacts.all();
  });
  await visit('/contacts?filter[firstname]=wibble&sort=-id');
});

不管我怎么调整上面的代码,Route的model函数里params.filter始终是空数组[]。

找到的旧方案(但不够理想)

我搜了这个场景的最佳实践,但没找到近期的资料。有个2015年的方案是可行的,但需要在Controller和Route里硬编码所有可能的filter键——这太不友好了,试想如果要处理20个以上的filter键会有多麻烦!

下面是用这个方案实现上述验收测试的代码:

Controller代码

import Controller from '@ember/controller';
export default Controller.extend({
  queryParams: ['sort', { firstnameFilter: 'filter[firstname]' } ],
  sort: 'id',
  firstnameFilter: null,
  init() {
    this._super(...arguments);
  }
});

Route代码

import Route from '@ember/routing/route';
export default Route.extend({
  queryParams: {
    firstnameFilter: { refreshModel: true },
    sort: { refreshModel: true }
  },
  model(params) {
    if (params.firstnameFilter) {
      params.filter = {};
      params.filter['firstname'] = params.firstnameFilter;
      delete params.firstnameFilter;
    }
    return this.get('store').query('contact', params);
  }
});

我真的希望能找到一个更优的解决方案!


内容的提问来源于stack exchange,提问作者casafred

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:42:40