Vue Router:如何将参数转换为整数而不是字符串?

问题描述 投票:0回答:7

当我使用浏览器字段输入 URL 时,参数将转换为字符串,而不是整数,例如

/user/1
返回
{id: "1"}
。但是,当使用
this.$route.push({})
时,参数正确地转换为整数
{id: 1}

这种行为是故意的吗?如果没有,我该如何解决?

vue.js vue-router
7个回答
43
投票

您必须自己处理任何参数值的转换。在路由对象中定义一个 props 函数。这是一个例子:

{
  path: '/user/:userId',
  component: UserProfile,
  props: (route) => {
    /**
     * This would preserve the other route.params object properties overriding only 
     * `userId` in case it exists with its integer equivalent, or otherwise with 
     * undefined.
     */
    return { ...route.params, ...{ userId: Number.parseInt(route.params.userId, 10) || undefined }
  }
}

链接到 vue router 文档,这是在功能模式下


4
投票

我可能参加聚会迟到了,但这是我对此的看法。我编写了一个函数,该函数返回一个函数,该函数将路由参数值转换为具有给定类型的同名属性。

function paramsToPropsCaster(mapping) {
  return function(route) {
    let nameType = Object.entries(mapping);  // [[param1, Number], [param2, String]]
    let nameRouteParam = nameType.map(([name, fn]) => [name, fn(route.params[name])]);  // [[param1, 1], [param2, "hello"]]
    let props = Object.fromEntries(nameRouteParam);  // {param1: 1, param2: "hello"}
    return props;
  }
}

然后,在您的路线定义中:

{
      path: '/projects/:param1/editor/:param2', 
      component: ProjectEditor,
      name: 'project-editor',
      props: paramsToPropsCaster({'param1': Number, 'param2': String}),
}

这只是提示您可以采取哪些措施来解决此处提出的问题,请勿逐字使用此内容!


1
投票

您可以在 props 中使用数组来支持这两种类型

props: { 
    type:[Number,String],
    required:true
}

1
投票

似乎 Vue Router 没有为此提供快捷方式,所以我想出了自己的快捷方式。下面的

castParams
函数生成一个内置指定类型转换的 props 函数。我添加了整数和布尔值的转换,但您可以轻松地将其扩展为您想要转换为的任何其他类型。

// casts should be an object where the keys are params that might appear in the route, and the values specify how to cast the parameters
const castParams = (casts) => {
    return (route) => {
        const props = {};
        for (var key in route.params) {
            const rawValue = route.params[key];
            const cast = casts[key];
            if (rawValue == null) {
                // Don't attempt to cast null or undefined values
                props[key] = rawValue;
            } else if (cast == null) {
                // No cast specified for this parameter
                props[key] = rawValue;
            } else if (cast == 'integer') {
                // Try to cast this parameter as an integer
                const castValue = Number.parseInt(rawValue, 10);
                props[key] = isNaN(castValue) ? rawValue : castValue;
            } else if (cast == 'boolean') {
                // Try to cast this parameter as a boolean
                if (rawValue === 'true' || rawValue === '1') {
                    props[key] = true;
                } else if (rawValue === 'false' || rawValue === '0') {
                    props[key] = false;
                } else {
                    props[key] = rawValue;
                }
            } else if (typeof(cast) == 'function') {
                // Use the supplied function to cast this param
                props[key] = cast(rawValue);
            } else {
                console.log("Unexpected route param cast", cast);
                props[key] = rawValue;
            }
        }
        return props;
    };
};

然后你可以在你的路由定义中使用它,例如:

{
    path: '/contact/:contactId',
    component: 'contact-details-page',
    props: castParams({contactId: 'integer'}),
},

0
投票

我确实更喜欢 Rodener Dajes 的答案,并在组件内而不是在路由定义中处理类型转换和验证:

props: {
        id: {
            type: [Number, String],
            default: 0
        },
    },

原因是它可以让我更简单、更易读地定义路线:

{
path: '/job/:id',
name: 'Job',
component: InvoiceJobDetail,
props: true
}

0
投票

其中许多解决方案对我来说似乎不必要的复杂。

这是我在项目中所做的 - 请注意,以

ID
结尾的路由参数或参数
id
本身会自动转换为
Number
,所以在我的情况下,我只需在几乎所有的我的路线。
props: typedProps(),

这可以使用一些错误处理,以防类型强制失败,但我会将其作为读者的练习:)


0
投票
https://stackoverflow.com/a/63897213

我想出了一个新包:https://www.npmjs.com/package/vue-router-parse-道具。它是用打字稿编写的并且有类型。请告诉我您的想法。 /** * Casts props into proper data types. * Props ending in 'ID' and the prop 'id' are cast to Number automatically. * To cast other props or override the defaults, pass a mapping like this: * @example * // Truthy values like 'true', 'yes', 'on' and '1' are converted to Boolean(true) * { * path: '/:isNice/:age/:hatSize', * name: 'foo route', * props: typedProps({ isNice: Boolean, age: Number, hatSize: Number}), * }, * @param {Object} mapping * @returns */ const typedProps = (mapping) => { if (!mapping) { mapping = {} } return (route) => { let props = {} for (let [prop, value] of Object.entries(route.params)) { if (prop in mapping) { if (mapping[prop] === Boolean) { value = ['true', '1', 'yes', 'on'].includes(value.toLowerCase()) } else { value = mapping[prop](value) } } else if (prop === 'id' || prop.endsWith('ID')) { value = Number(value) } props[prop] = value } return props } }

npm i vue-router-parse-props
© www.soinside.com 2019 - 2024. All rights reserved.