/src/assets/a.json
{ "data": [ { "id":1, "name": "hello", "price": 20 }, { "id":2, "name": "vite", "price": 30 }, { "id":3, "name": "pinia", "price": 14 } ] }
复制
vscode插件: JSON to TS
json文件的ts代码如何生成:
1、选中json文件的内容
2、windows: ctrl+shift+alt+s
mac: control+shift+option+s
得到的内容:

/src/router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"; const routes: Array<RouteRecordRaw> = [ { path: '/detail', name: 'detail', component: () => import('../components/Detail.vue') } ]; const router = createRouter({ history: createWebHashHistory(), routes }) export default router;
复制
1、query传参: url会带参数
/src/App.vue
<script setup lang="ts"> import { data } from "./assets/a.json"; import { useRouter } from "vue-router"; const router = useRouter(); type Datum = { id: number; name: string; price: number; } const toAction = (item: Datum) => { // query传参,和path搭配或者和name搭配,都可以,二选一 // 和path搭配 // router.push({ // path: '/detail', // query: item // }); // 和name搭配 router.push({ name: 'detail', query: item }); } </script> <template> <div class="page"> <table cellspacing="0" border="1"> <thead> <tr> <th>姓名</th> <th>年龄</th> <th>操作</th> </tr> </thead> <tbody> <tr v-for="item in data" :key="item.name"> <td>{{ item.name }}</td> <td>{{ item.price }}元</td> <td> <button @click="toAction(item)">点击一下</button> </td> </tr> </tbody> </table> </div> <router-view></router-view> </template> <style> html, body, #app, .page { width: 100%; height: 100%; } .page { position: absolute; left: 0; right: 0; top: 0; bottom: 0; } a { margin-left: 20px; } td { padding: 10px; } tbody tr td { padding: 20px; } </style>
复制
/src/components/Detail.vue
<script setup lang="ts"> import { useRoute, useRouter } from "vue-router"; // 当前路由的信息 const route = useRoute(); // vue路由对象 const router = useRouter(); </script> <template> <div class="page"> <h1>detail</h1> <!-- router.back():🔙返回到上一页 --> <button @click="router.back();">回退</button> <!-- 通过route.query获取url的参数值,这种方式传参,刷新页面数据不会消失 --> <!-- 举例url:http://localhost:5174/#/detail?id=1&name=hello&price=20 --> <p>id:{{ route.query.id }}</p> <p>姓名:{{ route.query.name }}</p> <p>价格:{{ route.query.price }}</p> </div> </template> <style scoped> .page { background: pink; } </style>
复制
2、params传参+动态路由传参: url会带参数
/src/router/index.ts改造成下面这样:
{ // 动态路由 path: '/detail/:id', name: 'detail', component: () => import('../components/Detail.vue'), }
复制
/src/App.vue的<script>部分改造成下面这样:
<script setup lang="ts"> import { data } from "./assets/a.json"; import { useRouter } from "vue-router"; const router = useRouter(); type Datum = { id: number; name: string; price: number; } const toAction = (item: Datum) => { // params传参 router.push({ name: 'detail', params: { id: item.id } }); } </script>
复制
/src/components/Detail.vue改造成下面这样:
<script setup lang="ts"> import { data } from "../assets/a.json"; import { useRoute, useRouter } from "vue-router"; const route = useRoute(); const router = useRouter(); // 通过route.params.id找到data里符合的数据 const itemData = data.find(item => item.id === Number(route.params.id)); </script> <template> <div class="page"> <h1>detail</h1> <button @click="router.back();">回退</button> <!-- 得到的url是这样的,3是id值:http://localhost:5174/#/detail/3 --> <!-- 刷新页面数据不会消失 --> <!-- 加❓问号是因为会提示:ts对象可能为未定义ts(18048) --> <p>id:{{ itemData?.id }}</p> <p>姓名:{{ itemData?.name }}</p> <p>价格:{{ itemData?.price }}</p> </div> </template> <style scoped> .page { background: pink; } </style>
复制
3、params传参: 如果没有和动态路由一起使用,详情页❌不可以通过route.params来获取参数值了

上图是Vue Router官网编程式导航的name和params的组合传参,如果没有和动态路由一起使用,详情页通过route.params来获取参数值,控制台会报警告⚠️,并且详情页得到的route.params是个空对象{}。

vue-router.js?v=5791c9af:42 [Vue Router warn]: Discarded invalid param(s) "id", "name", "price" when navigating. See https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22 for more details.
这是于2022年8月22日4.1.4版本的路由开始设置的,这样做的原因是“刷新页面获取到的参数会丢失”,详见https://github.com/vuejs/router/blob/main/packages/router/CHANGELOG.md#414-2022-08-22。
修改方案:见路由传参的其他方式
4、可以用History API的state传参: url不会带参数
/src/App.vue的<script>部分改造成下面这样:
<script setup lang="ts"> import { data } from "./assets/a.json"; import { useRouter } from "vue-router"; const router = useRouter(); type Datum = { id: number; name: string; price: number; } const toAction = (item: Datum) => { // history api的state传参 router.push({ name: 'detail', state: item }); } </script>
复制
/src/components/Detail.vue改造成下面这样:
<script setup lang="ts"> import { useRouter } from "vue-router"; const router = useRouter(); const state = history.state; </script> <template> <div class="page"> <h1>detail</h1> <button @click="router.back();">回退</button> <!-- 通过History API的state获取参数值,刷新页面数据不会消失 --> <p>id:{{ state.id }}</p> <p>姓名:{{ state.name }}</p> <p>价格:{{ state.price }}</p> </div> </template> <style scoped> .page { background: pink; } </style>
复制
5、将参数作为一个新属性传递给to.meta
这是已知的瞬间状态,并且由于它在导航守卫中,因此在重新加载页面时将被保留
router.beforeEach(async to => { if (to.meta.shouldFetch) { // name `data` whatever you want to.meta.data = await fetchSomething() } })
复制