关于Vue-Router @3 @4 版本的路由传参问题

925 阅读2分钟

问题

再写 vue3 + ts + vite 项目的时候用到了路由,但是实际使用的时候出现了问题,把问题记录一下

vue-router@3 路由传参

1 传参方式 -- query

特点: 参数显示在路径上,刷新保留数据

A.vue

methods{
    toPush(item){
        this.$router.push({
            path: '/B',
            query:{
                data
            }
        })
    }
}

B

 // 通过 this.$route.query 可以获取到数据
 this.$route.query.data

2 传参方式 --- params

  • 路径显示参数 特点: 路径显示参数, 刷新保留数据, 需在路由配置匹配

router.js

{
    path: '/B/:id',
    name:' B',
    component:-----
}

A.vue

注意需指定name ---> 路由名称

methods{
    toPush(item){
        
        this.$router.push({
            name: 'B',
            query:{
                id: 1234
            }
        })
    }
}

获取

this.$route.params

  • 路径不显示参数

特点: 参数不显示在路径上,刷新不保留数据

router.ts

{
    path: '/B',
    name:' B',
    component:-----
}

A.vue

methods{
    toPush(item){
        this.$router.push({
            name: 'B',
            query:{
                id: 1234
            }
        })
    }
}

获取方式无太大区别


vue-router@4 路由传参

其实和三版本区别不大

这里写一个简单示例(将home路由下的数据传递给like路由)

query 方式

home路由组件

<script lang='ts' setup>
import { reactive } from 'vue';

// 使用路由
import { useRouter } from 'vue-router';

const router = useRouter();

// 接口参数说明
/* 
    @ interface MyList params {
        id : 唯一标识
        city : 城市
        climate : 气候
        more : 更多
    }

*/

interface MyList {
    readonly id: number | string;
    city: string;
    climate: string;
    more?: string[]
}

// 这里定义默认数据
let objLIst = reactive<MyList[]>([
    { id: 0, city: '北京', climate: '晴朗' },
    { id: 1, city: '上海', climate: '多云' },
    { id: 3, city: '南宁', climate: '小雨' }])

// 跳转方法
const toPush = (item: MyList): void => {

}

</script>

<template>
    <h1>home</h1>
    <h3>query传递参数</h3>
    <button @click="toPush(item)" v-for="item in objLIst" :key="item.id">传递给like路由的数据(query){{item.id}}</button>
</template>

home页面

QQ截图20220923202959.png

like

<script lang='ts' setup>
import { toRefs, reactive, ref } from 'vue';
import { useRoute } from 'vue-router'

// 获取路由参数
const route = useRoute();

 let data = reactive(JSON.parse((route.query.res)!.toString()))


 let { id, city, climate } = toRefs(data)

</script>

<template>
    <h1>like</h1>
    <hr>
    <h3>query</h3>

    <ul>
        <li>id:{{id}}</li>
        <li>city:{{city}}</li>
        <li>climate:{{climate}} </li>
    </ul>
</template>

router.ts

const stateRouterLists: Array<RouteRecordRaw> = [{
    path: '/',
    name: 'index',
    component: () => import('@/views/home/index.vue')
}, {
    path: '/like',
    name: 'like',
    component: () => import('@/views/like/index.vue')
}, {
    path: '/login',
    name: 'login',
    component: () => import('@/views/login/index.vue')
}, {
    path: '/error',
    name: '404',
    component: () => import('@/views/login/index.vue')
}]

访问可以拿到数据, 路径上也有参数, 刷新不丢失数据

http://127.0.0.1:5173/#/like?res={"id":0,"city":"北京","climate":"晴朗"}


params 显示路径

router.ts

{
    path: '/',
    name: 'index',
    component: () => import('@/views/home/index.vue')
}, {
    path: '/like/:id',
    name: 'like',
    component: () => import('@/views/like/index.vue')
}

home路由组件

<script lang='ts' setup>
import { reactive } from 'vue';
import { useRouter } from 'vue-router';

const router = useRouter();
/* 
    @ interface MyList params {
        id : 唯一标识
        city : 城市
        climate : 气候
        more : 更多
    }

*/

interface MyList {
    readonly id: number | string;
    city: string;
    climate: string;
    more?: string[]
}

let objLIst = reactive<MyList[]>([
    { id: 0, city: '北京', climate: '晴朗' },
    { id: 1, city: '上海', climate: '多云' },
    { id: 3, city: '南宁', climate: '小雨' }])


const toPush1 = (id: number | string): void => {
    router.push({
        name: 'like',
        params: {
            id
        }
    })
}
</script>

<template>
    <h1>home</h1>
    <h3>params传递参数</h3>
    <button @click="toPush1(item.id)" v-for="item in objLIst" :key="item.id">传递给like路由的数据(params){{item.id}}</button>
</template>

like

<script lang='ts' setup>
import { toRefs, reactive, ref } from 'vue';
import { useRoute } from 'vue-router'

const route = useRoute();

 let data1 = ref(route.params.id);

// 假设是vuex中的数据
 interface MyList {
     readonly id: number | string;/     city: string;
     climate: string;
     more?: string[]
 }

 let objLIst = reactive<MyList[]>([
     { id: 0, city: '北京', climate: '晴朗' },
     { id: 1, city: '上海', climate: '多云' },
     { id: 3, city: '南宁', climate: '小雨' }])

 let { id, city, climate } = toRefs(objLIst.find((item) => data1.value == item.id) || { id: -1, city: '', climate: '' })
</script>

<template>
    <h1>like</h1>
    <h3>params</h3>
    <ul>
        <li>id:{{id}}</li>
        <li>city:{{city}}</li>
        <li>climate:{{climate}} </li>
    </ul>
</template>

访问可以拿到数据, 路径上也有参数, 刷新不丢失数据

http://127.0.0.1:5173/#/like/0


关键的第三种方式

在实际使用中我发现route.params 拿不到数据

并且浏览器vue报了一个警告

[Vue Router warn]: Discarded invalid param(s) "id" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.

进入链接

大概就是说,这种用法如果没有在路由表上面声明动态参数,将会造成刷新后参数丢失。
在 v4.1.4 版本的更新中,增加了删除未使用的参数这个功能。所以会提示你 Discarded invalid param(s) "name", "price", "id"(丢弃无效的参数 "name""price""id")。

如果想要解决,可以在路由表中声明你用到的这些参数,或者使用 query 的形式来传递参数。也可以用 vuex 之类的状态管理来暂存。`