路由
1、对路由的理解
2、基本使用
安装路由器扩展包
npm i vue-router
创建组件:
Home.vue
<template><div class="home"><img src="https://oss.fmy90.cn/fmy/public/4db8dec4d2eb31b8b0456cb42a907941.png" alt=""></div>
</template><script setup lang="ts" name="Home"></script><style scoped>
.home {display: flex;justify-content: center;align-items: center;height: 100%;
}
</style>
News.vue
<template><div class="news"><ul><li><a href="#">新闻001</a></li><li><a href="#">新闻002</a></li><li><a href="#">新闻003</a></li><li><a href="#">新闻004</a></li></ul></div>
</template><script setup lang="ts" name="News"></script><style scoped>
/* 新闻 */
.news {padding: 0 20px;display: flex;justify-content: space-between;height: 100%;
}.news ul {margin-top: 30px;list-style: none;padding-left: 10px;
}.news li>a {font-size: 18px;line-height: 40px;text-decoration: none;color: #64967E;text-shadow: 0 0 1px rgb(0, 84, 0);
}.news-content {width: 70%;height: 90%;border: 1px solid;margin-top: 20px;border-radius: 10px;
}
</style>
About.vue
<template><div class="about"><h2>大家好,欢迎来到新世界</h2></div>
</template><script setup lang="ts" name="About"></script><style scoped>
.about {display: flex;justify-content: center;align-items: center;height: 100%;color: rgb(85, 84, 84);font-size: 18px;
}
</style>
定义路由:
src/router/index.ts
// 创建路由器,并暴露出去// 第一步:引入
import { createRouter, createWebHistory } from 'vue-router'import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'// 第二步:创建路由器
const router = createRouter({history: createWebHistory(),routes: [{path: "/home",component: Home},{path: "/news",component: News},{path: "/about",component: About}]
})export default router;
使用路由器:
src/main.ts
// 引入 createApp 用于创建应用
import { createApp } from 'vue'// 引入 App 根组件
import App from './App.vue'// 引入路由器
import router from './router'// 创建一个应用
const app = createApp(App)// 使用路由器
app.use(router)// 挂载整个应用到 app 容器中
app.mount('#app')
渲染组件:
src/App.vue
<template><div class="app"><h2>Vue路由测试</h2><!-- 导航区 --><div class="navigate"><!-- vue-router 不使用 a 标签跳转,需使用 RouterLink --><!-- <a href="#">首页</a><a href="#">新闻</a><a href="#">关于</a> --><RouterLink to="/home" active-class="active">首页</RouterLink><RouterLink to="/news" active-class="active">新闻</RouterLink><RouterLink to="/about" active-class="active">关于</RouterLink></div><!-- 展示区 --><div class="main-content"><!-- 引入 RouterView 并使用,告知路由渲染区域 --><RouterView></RouterView></div></div>
</template><script lang="ts" setup name="App">
import { RouterView, RouterLink } from 'vue-router';
</script><style scoped>
.title {text-align: center;word-spacing: 5px;margin: 30px 0;height: 70px;line-height: 70px;background-image: linear-gradient(45deg, gray, white);border-radius: 10px;box-shadow: 0 0 2px;font-size: 30px;
}.navigate {display: flex;justify-content: space-around;margin: 0 100px;
}.navigate a {display: block;text-align: center;width: 90px;height: 40px;line-height: 40px;border-radius: 10px;background-color: gray;text-decoration: none;color: white;font-size: 18px;letter-spacing: 5px;
}.navigate a.active {background-color: #64967E;color: #ffc268;font-weight: 900;text-shadow: 0 0 1px black;font-family: 微软雅黑;
}.main-content {margin: 0 auto;margin-top: 30px;border-radius: 10px;width: 90%;height: 400px;border: 1px solid;
}
</style>
两个注意点:
路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
3、路由器工作模式
3.1 history
模式
优点:
URL
更加美观,不带有#
,更接近传统的网站URL
。缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。
示例代码:
const router = createRouter({history:createWebHistory(), // history模式
})
3.2 hash
模式
优点:兼容性更好,因为不需要服务器端处理路径。
缺点:
URL
带有#
不太美观,且在SEO
优化方面相对较差。
示例代码:
const router = createRouter({history:createWebHashHistory(), // hash模式
})
4、to 的两种写法
<!-- 第一种:to 的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link><!-- 第二种:to 的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">主页</router-link>
5、命名路由
作用:可以简化路由跳转及传参
路由规则命名:
routes:[{name:'zhuye',path:'/home',component:Home},{name:'xinwen',path:'/news',component:News,},{name:'guanyu',path:'/about',component:About}
]
跳转路由:
<!--简化前:需要写完整的路径(to的字符串写法) -->
<router-link to="/news">跳转</router-link><!--简化后:直接通过名字跳转(to的对象写法配合name属性) -->
<router-link :to="{name:'guanyu'}">跳转</router-link>
6、嵌套路由
1、编写 News
的子路由:Detail.vue
src/component/Detail.vue
<template><ul class="news-list"><li>编号:xxx</li><li>标题:xxx</li><li>内容:xxx</li></ul>
</template><script setup lang="ts" name="Detail"></script><style scoped>
.news-list {list-style: none;padding-left: 20px;
}.news-list>li {line-height: 30px;
}
</style>
2、配置路由规则,使用 children
配置项
src/router/index.ts
// 创建路由器,并暴露出去// 第一步:引入
import { createRouter, createWebHistory } from 'vue-router'import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
import Detail from '@/components/Detail.vue'// 第二步:创建路由器
const router = createRouter({history: createWebHistory(),routes: [{path: "/home",component: Home},{path: "/news",component: News,children: [{name: "xiangqing",path: "detail",component: Detail}]},{path: "/about",component: About}]
})export default router;
3、 设置页面跳转地址
src/component/News.vue
<template><div class="news"><!-- 导航区 --><ul><li v-for="item in newsList" :key="item.id"><!-- 需要指定完整跳转地址 --><RouterLink to="/news/detail" active-class="active">{{ item.title }}</RouterLink><!-- 或 --><!-- <router-link :to="{ path: '/news/detail' }">{{ item.title }}</router-link> --></li></ul><!-- 展示区 --><div class="news-content"><RouterView></RouterView></div></div>
</template><script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink } from 'vue-router';const newsList = reactive([{ id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },{ id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },{ id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },{ id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])
</script><style scoped>
/* 新闻 */
.news {padding: 0 20px;display: flex;justify-content: space-between;height: 100%;
}.news ul {margin-top: 30px;list-style: none;padding-left: 10px;
}.news li>a {font-size: 18px;line-height: 40px;text-decoration: none;color: #64967E;text-shadow: 0 0 1px rgb(0, 84, 0);
}.news-content {width: 70%;height: 90%;border: 1px solid;margin-top: 20px;border-radius: 10px;
}
</style>
7、路由传参
7.1 query 参数
1.传递参数
<!-- 跳转并携带query参数(to的字符串写法) -->
<router-link to="/news/detail?a=1&b=2&content=欢迎你">跳转
</router-link><!-- 跳转并携带query参数(to的对象写法) -->
<RouterLink :to="{//name:'xiang', // 用name也可以跳转path: '/news/detail',query: {id: news.id,title: news.title,content: news.content}
}">{{ news.title }}
</RouterLink>
2.接收参数
import { useRoute } from 'vue-router'const route = useRoute()console.log(route.query)
7.2 params 传参
传递
params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。传递
params
参数时,需要提前在规则中占位。
- 路由站位
{path: "/news",component: News,children: [{name: "xiangqing",path: "detail/:id/:title/:content?", // :id 站位,"?" 代表可选component: Detail}]
}
- 发送参数 News.vue
<template><div class="news"><!-- 导航区 --><ul><li v-for="item in newsList" :key="item.id"><!-- 跳转并携带params参数(to的字符串写法) --><!-- <RouterLink :to="`/news/detail/${item.id}/${item.title}/${item.content}`">{{ item.title }}</RouterLink> --><!-- 跳转并携带 params 参数(to的对象写法) --><RouterLink :to="{name: 'xiangqing', // 只能用路由的 name 跳转params: {id: item.id,title: item.title,content: item.title}}">{{ item.title }}</RouterLink></li></ul><!-- 展示区 --><div class="news-content"><RouterView></RouterView></div></div>
</template><script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink } from 'vue-router';const newsList = reactive([{ id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },{ id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },{ id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },{ id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])
</script><style scoped>
/* 新闻 */
.news {padding: 0 20px;display: flex;justify-content: space-between;height: 100%;
}.news ul {margin-top: 30px;list-style: none;padding-left: 10px;
}.news li>a {font-size: 18px;line-height: 40px;text-decoration: none;color: #64967E;text-shadow: 0 0 1px rgb(0, 84, 0);
}.news-content {width: 70%;height: 90%;border: 1px solid;margin-top: 20px;border-radius: 10px;
}
</style>
- 接收参数 Detail.vue
<template><ul class="news-list"><li>编号:{{ params.id }}</li><li>标题:{{ params.title }}</li><li>内容:{{ params.content }}</li></ul>
</template><script setup lang="ts" name="Detail">
import { useRoute } from 'vue-router'
import { toRefs } from 'vue';const route = useRoute()let { params } = toRefs(route)
</script><style scoped>
.news-list {list-style: none;padding-left: 20px;
}.news-list>li {line-height: 30px;
}
</style>
8、路由的 props 配置
作用:让路由组件更方便的收到参数(可以将路由参数作为 props
传给组件)
- 路由开启 prop 传参
// 创建路由器,并暴露出去// 第一步:引入
import { createRouter, createWebHistory } from 'vue-router'import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
import Detail from '@/components/Detail.vue'// 第二步:创建路由器
const router = createRouter({history: createWebHistory(),routes: [{path: "/home",component: Home},{path: "/news",component: News,children: [{name: "xiangqing",path: "detail/:id/:title/:content?",component: Detail,// 写法1:props 的布尔值写法,作用:将路由接收到的所有 params 参数,作为 props 传给 Detail 组件。Detail 中可以使用 defineProp 方法接收参数props: true// 写法2:props 的函数写法,作用:把返回的对象中每一组 key-value 作为 props 传给 Detail 组件。// props(route) {// return route.query// }// 写法3:props 的对象写法,作用:把对象中的每一组 key-value 作为 props 传给 Detail 组件// props:{a:1,b:2,c:3}}]},{path: "/about",component: About}]
})export default router;
2.接受参数,Detail.vue
<template><ul class="news-list"><li>编号:{{ id }}</li><li>标题:{{ title }}</li><li>内容:{{ content }}</li></ul>
</template><script setup lang="ts" name="Detail">
// 组件接受参数
defineProps(['id', 'title', 'content'])
</script><style scoped>
.news-list {list-style: none;padding-left: 20px;
}.news-list>li {line-height: 30px;
}
</style>
9、replace 属性
-
作用:控制路由跳转时操作浏览器历史记录的模式。
-
浏览器的历史记录有两种写入方式:分别为
push
和replace
:
push
是追加历史记录(默认值)。replace
是替换当前记录,无法操作后退
- 开启
replace
模式:
<RouterLink replace >News</RouterLink>
10、编程式导航
代码示例:
<template><div class="news"><!-- 导航区 --><ul><li v-for="item in newsList" :key="item.id"><button @click="showDetail(`${item.id}`)">查看详情</button><!-- 跳转并携带params参数(to的字符串写法) --><!-- <RouterLink :to="`/news/detail/${item.id}/${item.title}/${item.content}`">{{ item.title }}</RouterLink> --><!-- 跳转并携带params参数(to的对象写法) --><RouterLink :to="{name: 'xiangqing', // 只能用 name 跳转params: {id: item.id,title: item.title,content: item.title}}">{{ item.title }}</RouterLink></li></ul><!-- 展示区 --><div class="news-content"><RouterView></RouterView></div></div>
</template><script setup lang="ts" name="News">
import { reactive } from 'vue'
import { RouterView, RouterLink, useRouter } from 'vue-router';interface newsInter {id: string,title: string,content: string
}
const newsList = reactive<newsInter[]>([{ id: 'asfdtrfay01', title: '很好的抗癌食物', content: '西蓝花' },{ id: 'asfdtrfay02', title: '如何一夜暴富', content: '学IT' },{ id: 'asfdtrfay03', title: '震惊,万万没想到', content: '明天是周一' },{ id: 'asfdtrfay04', title: '好消息!好消息!', content: '快过年了' }
])let router = useRouter()function showDetail(id: string) {const news = newsList.find(item => item.id == id) as newsInter// to 如何写,push 就可以怎样写router.push({name: 'xiangqing', // 只能用 name 跳转params: {id: news.id,title: news.title,content: news.title}})
}</script><style scoped>
/* 新闻 */
.news {padding: 0 20px;display: flex;justify-content: space-between;height: 100%;
}.news ul {margin-top: 30px;list-style: none;padding-left: 10px;
}.news li>a {font-size: 18px;line-height: 40px;text-decoration: none;color: #64967E;text-shadow: 0 0 1px rgb(0, 84, 0);
}.news-content {width: 70%;height: 90%;border: 1px solid;margin-top: 20px;border-radius: 10px;
}button {margin-right: 10px;
}
</style>
12、重定向
-
作用:将特定的路径,重新定向到已有路由。
-
路由文件,具体编码:
{path:'/',redirect:'/about' }