✅ Query要点提炼query传参 嵌套路由你的项目嵌套路由 query传参News是父路由Detail是它的子路由1. 路由配置要点子路由写在父路由的children数组里{ path: /news, component: News, children:[ { path: detail, // ⚠️ 子路由path不要写 /detail写了就不是嵌套 name:xiangqing, component: Detail, } ] }子路由不带/拼接父路径 →/news/detail正确嵌套子路由写/detail变成根级路由不再嵌套嵌套路由必须在父组件News.vue里面写RouterView用来渲染子组件DetailApp里的RouterView渲染一级路由/news、/aboutNews里面的RouterView渲染它的子路由/news/detail2. Query传参你当前用的方式跳转写法命名路由 queryRouterLink :to{ name:xiangqing, // 推荐用name跳转路径改了不用到处改 query:{id:news.id,title:news.title,content:news.content} }query传参参数会拼在url后面/news/detail?idxxxtitlexxx特点参数在地址栏可见刷新页面参数不会丢失也可以用path写法:to{ path:/news/detail, query:{id:xxx} }对比params传参是放在路径里刷新容易丢失如果不是动态路径/:id本案例没有用params3. 子组件接收 query 参数重点对应你刚才问的解构import {useRoute} from vue-router import {toRefs} from vue; let route useRoute(); let {query} toRefs(route);useRoute()拿到当前路由信息对象只读不要用来跳转toRefs(route)把route里面的属性转为ref保留响应式const { query } toRefs(route)对象解构取出query这个ref模板里直接写{{ query.id }}ref模板自动解包不用.valuescript里JS代码取值query.value.id❌ 坑如果直接const query route.query拿到的不是refscript里监听会丢失响应性4. 区分两个容易搞混的hookuseRoute()→ 获取当前路由信息path/query/params读参数用useRouter()→ 获取路由实例编程式跳转router.push()5. Query传参优缺点✅ 优点刷新页面参数保留、调试方便、适合简单传参 ❌ 缺点url暴露参数适合非敏感数据url长度有限制不能传大量数据6. 本案例关键坑总结嵌套子路由path不加/嵌套路由父组件必须放RouterView承载子组件{name:xxx}命名路由跳转要先在路由配置写上namequery参数模板直接用script里ref要.value不要写let {route} useRoute()useRoute返回的对象没有route属性let{route} useRoute() 本意是 let route useRoute().route补充拓展可选方便你对比如果以后用动态路由params传参写法不一样//路由 path: detail/:id //跳转 :to{name:xiangqing, params:{id: news.id}} //接收 const { params } toRefs(route)要不要我帮你把这个案例改成动态params传参版本对比学习########src/router/index.ts import {createRouter, createWebHistory, createWebHashHistory} from vue-router import Abouts from /components/Abouts.vue import News from /components/News.vue import Home from /components/Home.vue import Detail from /components/Detail.vue; /** * 路由映射 * 地址与组件的映射 */ const routes [ { path: /about, component: Abouts }, { path: /news, component: News, children:[ { path: detail, name:xiangqing, component: Detail, } ] } , { path: /home, component: Home, name: zhuye } ] /** * 将路由器暴露出去 */ export default createRouter({ //history: createWebHashHistory(),// http://localhost:5173/#/about history: createWebHistory(),// http://localhost:5173/about routes })#####App.vue template div classapp h1Vue Router 示例/h1 /div nav classnav RouterLink to/news新闻/RouterLink RouterLink :to{path:/about}关于/RouterLink RouterLink :to{name:zhuye}主页/RouterLink /nav div classmain-content !--展示组件 -- RouterView/RouterView /div /template script langts //导出组件名称叫做App export default { name :App } /script script langts setup /script style scoped .app { background-color: #3b82f6; color: white; padding: 16px 24px; border-radius: 8px; margin-bottom: 16px; } .app h1 { margin: 0; font-size: 20px; } .nav { display: flex; gap: 12px; padding: 12px 0; border-bottom: 1px solid #e5e7eb; margin-bottom: 16px; } .nav a { padding: 8px 16px; text-decoration: none; color: #374151; border-radius: 6px; transition: background-color 0.2s, color 0.2s; } .nav a:hover { background-color: #f3f4f6; } /* 当前匹配的路由链接会添加 router-link-active 类 */ .nav a.router-link-active { background-color: #3b82f6; color: white; font-weight: 600; } /* 精确匹配当前路由 */ .nav a.router-link-exact-active { background-color: #2563eb; } .main-content { padding: 16px; background-color: #f9fafb; border-radius: 8px; min-height: 200px; } /style#############News.vue template h1新闻/h1 div classnews-layout ul classnews-list li v-fornews in newsList :keynews.id RouterLink :to { name:xiangqing, query:{id:news.id,title:news.title,content:news.content} } {{ news.title }} /RouterLink /li /ul div classnews-detail RouterView/RouterView /div /div /template script langts //导出组件名称叫做Person export default { name: News } /script script langts setup import {reactive} from vue let newsList reactive([ {id: asdsad001, title: 标题1, content: 内容1}, {id: asdsad002, title: 标题2, content: 内容2}, {id: asdsad003, title: 标题3, content: 内容3}, {id: asdsad004, title: 标题4, content: 内容4} ]) /script style scoped .news-layout { display: flex; gap: 24px; align-items: flex-start; } .news-list { list-style: none; padding: 0; margin: 0; width: 200px; border-right: 1px solid #e5e7eb; padding-right: 16px; } .news-list li { margin-bottom: 8px; } .news-list a { text-decoration: none; color: #374151; padding: 6px 10px; display: block; border-radius: 4px; transition: background-color 0.2s, color 0.2s; } .news-list a:hover { background-color: #f3f4f6; } .news-list a.router-link-exact-active { background-color: #3b82f6; color: white; } .news-detail { flex: 1; padding: 16px; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; min-height: 150px; } /style################Detail.vue template ul liid:{{ query.id }}/li li标题:{{ query.title }}/li li内容:{{ query.content }}/li /ul /template script langts //导出组件名称叫做Person export default { name: Detail } /script script langts setup import {useRoute} from vue-router import {toRefs} from vue; // useRoute当前路由对象包含 params、query 等 // useRouter路由器实例用来 push、replace 跳转 let route useRoute(); //这样写的意思是route useRoute().route //let {route} useRoute(); let {query} toRefs(route); console.log(route:, route) console.log(query:, query.value) /script style scoped /style✅ 嵌套路由 params 动态参数 要点总结一、路由配置 router/index.ts嵌套路由 children子路由属于父路由子路由的path不要加/加/代表根路由父路由组件News.vue内部必须写RouterView/子组件Detail才会渲染在父组件里面{ path: /news, component: News, children: [ // 访问地址/news/detail/xxx/xxx/xxx { path: detail/:id/:title/:content?, name: xiangqing, component: Detail, } ] }动态params参数占位:id、:title必传参数不传匹配失败:content??代表可选参数可以不传路由两种跳转标识path路径跳转name命名路由跳转传params推荐用name模式createWebHistory()地址不带#二、News.vue父路由组件嵌套路由核心父组件放RouterView子页面渲染在这里RouterLink传params参数✅ 传params优先使用 name命名路由不能直接写path语法:to{ name: xiangqing, params: {id,title,content} }⚠️ 区分params是路径上的参数拼接在url路径里query是url?后面的参数数据reactive定义新闻列表v-for循环渲染列表绑定key注意to前面必须加:是动态绑定不是静态字符串三、Detail.vue子组件接收params两个核心组合式APIvue-router提供useRoute()当前路由信息对象只读里面有 params、query、path、nameuseRouter()路由操作对象用来编程式跳转push/replace/go响应式取值const route useRoute() const { params, query } toRefs(route)重点route.params是ref响应式对象直接解构会丢失响应式要用toRefs在模板里直接写{{ params.id }}script里取值要.value→params.id.value控制台打印query.value因为query是refscript中访问需要.value四、高频重点坑点面试常问✅ params 参数必须在路由规则里提前占位:xxxquery不需要占位✅ params name 配套如果写path传paramsvue-router4会直接失效✅ 子路由path不加/加/会变成根路由不再是嵌套✅?代表参数可选不传不会404✅useRoute是当前路由信息读useRouter是路由实例写、跳转不要搞混✅toRefs作用把 reactive 对象的属性转为 ref保留响应式❌ 不写父组件的RouterView→ 子组件永远渲染不出来❌ 不要直接const {params} useRoute()会丢失响应式五、url效果演示/news/detail/asdsad001/标题1/内容1content传了/news/detail/asdsad004/标题4content是可选省略也能正常访问六、区分一句话query/news?id1titlexxx参数在问号后面路由不需要占位params/news/detail/1/标题参数嵌入路径路由必须提前:占位// src/router/index.ts import {createRouter, createWebHistory} from vue-router import Abouts from /components/Abouts.vue import News from /components/News.vue import Home from /components/Home.vue import Detail from /components/Detail.vue; /** * 路由映射 * 地址与组件的映射 */ const routes [ { path: /about, component: Abouts }, { path: /news, component: News, children: [ //这种就是 定义 params参数传递方式 ?代表可选的 { path: detail/:id/:title/:content?, name: xiangqing, component: Detail, } ] } , { path: /home, component: Home, name: zhuye } ] /** * 将路由器暴露出去 */ export default createRouter({ //history: createWebHashHistory(),// http://localhost:5173/#/about history: createWebHistory(),// http://localhost:5173/about routes })#################News.vue 父组件 template h1新闻/h1 div classnews-layout ul classnews-list li v-fornews in newsList :keynews.id !-- 这里需要写:to意思是需要计算 -- RouterLink :to { //要点1传递params参数时需要提前在规则中占位 //路由ts里需要定义参数 path: detail/:id/:title/:content? //要点2并且父组件必须要使用name进行指定子组件路由不能用path指定 name:xiangqing, //query:{id:news.id,title:news.title,content:news.content} params:{ id:news.id, title:news.title, content:news.content } } {{ news.title }} /RouterLink /li /ul div classnews-detail RouterView/RouterView /div /div /template !--script langts -- !--//导出组件名称叫做Person-- !--export default {-- !-- name: News-- !--}-- !--/script-- script langts setup nameNews import {reactive} from vue let newsList reactive([ {id: asdsad001, title: 标题1, content: 内容1}, {id: asdsad002, title: 标题2, content: 内容2}, {id: asdsad003, title: 标题3, content: 内容3}, {id: asdsad004, title: 标题4} ]) /script style scoped .news-layout { display: flex; gap: 24px; align-items: flex-start; } .news-list { list-style: none; padding: 0; margin: 0; width: 200px; border-right: 1px solid #e5e7eb; padding-right: 16px; } .news-list li { margin-bottom: 8px; } .news-list a { text-decoration: none; color: #374151; padding: 6px 10px; display: block; border-radius: 4px; transition: background-color 0.2s, color 0.2s; } .news-list a:hover { background-color: #f3f4f6; } .news-list a.router-link-exact-active { background-color: #3b82f6; color: white; } .news-detail { flex: 1; padding: 16px; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; min-height: 150px; } /style###############子组件 template ul liid:{{ params.id }}/li li标题:{{ params.title }}/li li内容:{{ params.content }}/li /ul /template script langts //导出组件名称叫做Person export default { name: Detail } /script script langts setup import {useRoute} from vue-router import {toRefs} from vue; // useRoute当前路由对象包含 params、query 等 // useRouter路由器实例用来 push、replace 跳转 let route useRoute(); //这样写的意思是route useRoute().route //let {route} useRoute(); let {query,params} toRefs(route); console.log(route:, route) console.log(params:, params) console.log(query:, query.value) /script style scoped /style✅ params路由ts定义 props:true defineProps 接收路由配置 router/index.ts{ path: detail/:id/:title/:content?, name: xiangqing, component: Detail, props: true // ✅ 开启路由匹配到的 params 自动转为组件 props }props: true生效范围仅 params 动态路径参数query 参数不会自动传给 props动态占位/:id/:title/:content??代表content可选参数可以不传嵌套路由子路由 path 不要加/父组件 News 内部必须有RouterViewparams 传参建议搭配命名路由namevue-router4 不推荐 path params(无效)模式createWebHistory()无 #上线后端需要配置重定向Detail.vue 配套写法新版解耦template ul liid:{{ id }}/li li标题:{{ title }}/li li内容:{{ content }}/li /ul /template script langts setup nameDetail // 接收路由传来的 props不用引入 useRoute defineProps([id,title,content]) /script✅ 优点组件不再依赖useRoute和路由解耦组件复用性更好模板直接{{ id }}不需要params.id、不需要 toRefs ⚠️ 注意content是可选参数可能为undefined模板直接渲染不会报错这种方式只能拿到 params拿不到 query想要 query 依旧要useRoute两种方案对比重点useRoute 方案耦合const route useRoute() const { params } toRefs(route) 组件强依赖 vue-router脱离路由就不能运行props:true defineProps 方案推荐defineProps([id,title,content]) 组件只声明需要什么参数来源可以是路由也可以是别的父组件传值解耦坑点汇总props:true只对 params 生效query 不行占位符必须提前在路由 path 定义否则参数无法传入子路由的props:true写在子路由对象上不是父路由可选参数content?不传的时候props.content 是 undefined一句话总结路由配置写props:true路由匹配的 params 自动作为组件 props在子组件用defineProps接收摆脱 useRoute实现组件和路由解耦。// src/router/index.ts import {createRouter, createWebHistory} from vue-router import Abouts from /components/Abouts.vue import News from /components/News.vue import Home from /components/Home.vue import Detail from /components/Detail.vue; /** * 路由映射 * 地址与组件的映射 */ const routes [ { path: /about, component: Abouts }, { path: /news, component: News, children: [ { path: detail/:id/:title/:content?, name: xiangqing, component: Detail, /** * 写法将路由收到的所有params参数作为props传给路由组件 * 注意必须配合params传参 * propstrue意思是上层Detail idxx titlexx contentxxx / */ props: true } ], } , { path: /home, component: Home, name: zhuye } ] /** * 将路由器暴露出去 */ export default createRouter({ //history: createWebHashHistory(),// http://localhost:5173/#/about history: createWebHistory(),// http://localhost:5173/about routes })###############News.vue template h1新闻/h1 div classnews-layout ul classnews-list li v-fornews in newsList :keynews.id !-- 这里需要写:to意思是需要计算 -- RouterLink :to { //要点1传递params参数时需要提前在规则中占位 //路由ts里需要定义参数 path: detail/:id/:title/:content? //要点2并且父组件必须要使用name进行指定子组件路由不能用path指定 name:xiangqing, //query:{id:news.id,title:news.title,content:news.content} params:{ id:news.id, title:news.title, content:news.content } } {{ news.title }} /RouterLink /li /ul div classnews-detail RouterView/RouterView /div /div /template !--script langts -- !--//导出组件名称叫做Person-- !--export default {-- !-- name: News-- !--}-- !--/script-- script langts setup nameNews import {reactive} from vue let newsList reactive([ {id: asdsad001, title: 标题1, content: 内容1}, {id: asdsad002, title: 标题2, content: 内容2}, {id: asdsad003, title: 标题3, content: 内容3}, {id: asdsad004, title: 标题4} ]) /script style scoped .news-layout { display: flex; gap: 24px; align-items: flex-start; } .news-list { list-style: none; padding: 0; margin: 0; width: 200px; border-right: 1px solid #e5e7eb; padding-right: 16px; } .news-list li { margin-bottom: 8px; } .news-list a { text-decoration: none; color: #374151; padding: 6px 10px; display: block; border-radius: 4px; transition: background-color 0.2s, color 0.2s; } .news-list a:hover { background-color: #f3f4f6; } .news-list a.router-link-exact-active { background-color: #3b82f6; color: white; } .news-detail { flex: 1; padding: 16px; background-color: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; min-height: 150px; } /style#########Detail.vue template ul liid:{{ id }}/li li标题:{{ title }}/li li内容:{{ content }}/li /ul /template script langts setup nameDetail defineProps([id,title,content]) /script style scoped /style
阅读完成 · 觉得有帮助?