Ember.js中查询参数的URL编码

7

我正在使用Ember.js,版本为1.7.0-beta.1,在我的最新项目中。我使用查询参数功能使列表在进行硬刷新后仍然保留选定项(例如,重新加载后,列表中选择的项目仍然被选中)。

我有一个控制器来管理这个功能:

export default Ember.ObjectController.extend({
    queryParams: [{selectedFiles: 'files'}],
    selectedFiles: Ember.A([]), //list of file ids

    ... //other props

    actions: {
    selectFile: function(file) {
        //set or remove the file id to the selectedFiles property
    }
});

它非常好用,但有一个条件:URL是经过编码的:

Chrome和IE:

path/354?files=%5B"6513"%2C"6455"%2C"6509"%2C"6507"%2C"6505"%2C"6504"%2C"6511"%5D

FF (自动设置括号):

path/354?files="6513"%2C"6455"%2C"6509"%2C"6507"%2C"6505"%2C"6504"%2C"6511"]

在Ember中是否有一种方法可以将查询参数字符串解码为更易读的格式?也许我可以在某个地方使用decodeURIComponent()函数?

期望的输出:

path/354?files=["6513","6455","6509","6507","6505","6504","6511"]


你需要使用 Ember.$.ajaxSettings.traditional = true;,请参考 https://discuss.emberjs.com/t/persisting-multiple-query-params-of-the-same-name/8174/4 - Alan Dong
1个回答

11

我曾经遇到过非常类似的问题,通过在路由中覆盖serializeQueryParamdeserializeQueryParam方法,最终解决了这个问题。

在控制器中,你需要这样写:

queryParams: ['files'],
files: []

在路由中:

  serializeQueryParam: function(value, urlKey, defaultValueType) {
    if (defaultValueType === 'array') {
      return value;

      // Original: return JSON.stringify(value);
    }
    return '' + value;
  }, 

并且:

  deserializeQueryParam: function(value, urlKey, defaultValueType) {

    if (defaultValueType === 'array') {

      var arr = [];
      for (var i = 0; i < value.length; i++) {
        arr.push(parseInt(value[i], 10));
      }      

      return arr;

      // Original: return Ember.A(JSON.parse(value));
    }

    if (defaultValueType === 'boolean') {
      return (value === 'true') ? true : false;
    } else if (defaultValueType === 'number') {
      return (Number(value)).valueOf();
    }
    return value;
  }, 

然后URL将变成类似于:

?files[]=1&files[]=2&files[]=3

这将在服务器端成为一个真实的数组。

在jsbin.com上查看这个工作示例


太棒了,这些钩子正是我所需要的。谢谢! - Jacob van Lingen
我尝试了上述方法,但是更改了deserializeQueryParam()以简单地返回value而不是对其每个值进行parseInt()。问题是,查询参数和控制器的files属性之间的绑定没有正确更新 - 似乎Ember没有意识到该值何时被更改。因此,我不得不在deserializeQueryParam()内部调用.copy()来使Ember注意到值何时被更新。如果其他人遇到此问题,这里有一些提示。 - jessepinho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接