路由基本使用
下载vue-router
npm install vue-router -S
配置router/index.ts
import {createRouter, createWebHistory, RouteRecordRaw} from "vue-router";
const routes:Array<RouteRecordRaw> = [{
path: "/",
component: () => import('../components/log.vue')
},{
path:"/reg",
component:() => import("../components/reg.vue")
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router
路由模式
- //vue2 mode history vue3 createWebHistory
- //vue2 mode hash vue3 createWebHashHistory
- //vue2 mode abstact vue3 createMemoryHistory
1.hash路由模式是比较好区分的,凡是我们的url后带有“#”的都属于hash模式;
2、hash“#”后的值,不会包含在http请求中,改变hash的值不会引起页面的重新加载(他是前端路由交互处理,#后面hash值变化不会导致浏览器像服务器发送请求,浏览器不发送请求,也就不会刷新页面);
3、hash原理:onhashchange事件,可以在window对象上监听这个事件(每次hash值的变化,都会出发hashchange事件,通过这个事件我们就可以知道hash值发生了哪些变化,通过监听hashchange来实现更新页面部分内容操作)
4、hash可以兼容到ie8以上
5、会创建hashhistory对象,在访问不同的路由会发生两种事件:hashhistory.push():将新的路由添加到浏览器访问的历史栈顶,hashhistory.replace()替换到当前栈
优点:兼容性好,安全
1、url不带参数,所以看起来比较美观;
2、history依赖于前后端交互,即将url修改的就和正常请求的后端url一样,如后端没有配置对应的/user/id的路由处理,就会返回404错误;
3、history原理:window的popstate事件,当浏览器跳转到新的状态时会触发popstate事件;
4、history可以兼容到ie10;
5.pushState()跳转页面
比较依赖于前后端交互,跳转时会重新发送请求
use router(main.ts挂载)
import router from "./router";
createApp(App).use(router).mount('#app')
router跳转方式
<div>
<router-link to="/">login</router-link>
<router-link to="/reg">reg</router-link>
</div>
<router-view></router-view>
router-view:路由的出口,配置的路由界面在此处渲染
router-link:点击跳转路由 其中的参数to=“”,为配置的path
命名路由,编程式导航
import {createRouter, createWebHistory, RouteRecordRaw} from "vue-router";
const routes:Array<RouteRecordRaw> = [{
path: "/",
name:"login",
component: () => import('../components/log.vue')
},{
path:"/reg",
name:"register",
component:() => import("../components/reg.vue")
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router
配置name属性
router-link跳转方式
<div>
<router-link :to="{name:'login'}">login</router-link>
<router-link :to="{name:'register'}">reg</router-link>
</div>
编程式跳转方式
- 字符串形式
//引入vue-router
import {useRouter} from "vue-router";
//必须为useRouter
const router = useRouter();
//页面跳转
const toPage = (url:string) => {
router.push(url)
}
- 对象形式
//引入vue-router
import {useRouter} from "vue-router";
//必须为useRouter
const router = useRouter();
//页面跳转
const toPage = (url:string) => {
router.push({
path:url
})
}
- 命名式路由导航
//引入vue-router
import {useRouter} from "vue-router";
//必须为useRouter
const router = useRouter();
//页面跳转
const toPage = (name:string) => {
router.push({
name
})
}
a标签也可以跳转,但是会刷新页面
<a href="/reg">rrr</a>
历史记录
<router-link :to="{name:'login'}" replace>login</router-link>
<router-link :to="{name:'register'}" replace>reg</router-link>
编程式
将.push方法改为replace方法
横跨历史
<button @click="next">前进</button>
<button @click="prev">后退</button>
const next = () => {
//前进 数量不限于1
router.go(1)
}
const prev = () => {
//后退
router.back()
}
路由传参
const toDetail = (item: Item) => {
router.push({
path: '/reg',
query: item
})
}
接受参数
使用 useRoute 的 query
<div>brand:{{route.query.name}}</div>
<div>price:{{route.query.price}}</div>
<div>id:{{route.query.id}}</div>
//取值使用useRoute
import {useRoute} from "vue-router";
const route = useRoute()
Params路由传参
const toDetail = (item: Item) => {
router.push({
name: 'Reg',
params: item
})
}
接收参数,使用params接收参数
import { useRoute } from 'vue-router';
const route = useRoute()
<div>品牌:{{ route.params?.name }}</div>
<div>价格:{{ route.params?.price }}</div>
<div>ID:{{ route.params?.id }}</div>
动态路由传参
很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数
路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件
const routes:Array<RouteRecordRaw> = [
{
path:"/",
name:"Login",
component:()=> import('../components/login.vue')
},
{
//动态路由参数
path:"/reg/:id",
name:"Reg",
component:()=> import('../components/reg.vue')
}
]
const toDetail = (item: Item) => {
router.push({
name: 'Reg',
params: {
id: item.id
}
})
}
import { useRoute } from 'vue-router';
import { data } from './list.json'
const route = useRoute()
const item = data.find(v => v.id === Number(route.params.id))
二者的区别
- query 传参配置的是 path,而 params 传参配置的是name,在 params中配置 path 无效
- query 在路由配置不需要设置参数,而 params 必须设置
- query 传递的参数会显示在地址栏中
- params传参刷新会无效,但是 query 会保存传递过来的值,刷新不变 ;
- 路由配置
嵌套路由
一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如:
const routes: Array<RouteRecordRaw> = [
{
path: "/user",
component: () => import('../components/footer.vue'),
children: [
{
path: "",
name: "Login",
component: () => import('../components/login.vue')
},
{
path: "reg",
name: "Reg",
component: () => import('../components/reg.vue')
}
]
},
]
如你所见,children 配置只是另一个路由数组,就像 routes 本身一样。因此,你可以根据自己的需要,不断地嵌套视图
TIPS:不要忘记写router-view
<div>
<router-view></router-view>
<div>
<router-link to="/">login</router-link>
<router-link style="margin-left:10px;" to="/user/reg">reg</router-link>
</div>
</div>
命名视图
- 有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容)
两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view
没有设置名字,那么默认为 default。
<router-view class="view left-sidebar" name="LeftSidebar"></router-view>
<router-view class="view main-content"></router-view>
<router-view class="view right-sidebar" name="RightSidebar"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
components: {
default: Home,
// LeftSidebar: LeftSidebar 的缩写
LeftSidebar,
// 它们与 `<router-view>` 上的 `name` 属性匹配
RightSidebar,
},
},
],
})
重定向和别名
重定向
重定向也是通过 routes 配置来完成,下面例子是从 /home 重定向到 /:
const routes = [{ path: '/home', redirect: '/' }]
重定向的目标也可以是一个命名的路由:
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
甚至是一个方法,动态返回重定向目标:
const routes = [
{
// /search/screens -> /search?q=screens
path: '/search/:searchText',
redirect: to => {
// 方法接收目标路由作为参数
// return 重定向的字符串路径/路径对象
return { path: '/search', query: { q: to.params.searchText } }
},
},
{
path: '/search',
// ...
},
]
请注意**,导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。**在上面的例子中,在 /home 路由中添加 beforeEnter 守卫不会有任何效果。
在写 redirect 的时候,可以省略 component 配置,因为它从来没有被直接访问过,所以没有组件要渲染。唯一的例外是嵌套路由:如果一个路由记录有 children 和 redirect 属性,它也应该有 component 属性。
相对重定向
也可以重定向到相对位置:
const routes = [
{
// 将总是把/users/123/posts重定向到/users/123/profile。
path: '/users/:id/posts',
redirect: to => {
// 该函数接收目标路由作为参数
// 相对位置不以`/`开头
// 或 { path: 'profile'}
return 'profile'
},
},
]
别名
重定向是指当用户访问 /home 时,URL 会被 / 替换,然后匹配成 /。那么什么是别名呢?
将 / 别名为 /home,意味着当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /。
上面对应的路由配置为:
const routes = [{ path: '/', component: Homepage, alias: '/home' }]
通过别名,你可以自由地将 UI 结构映射到一个任意的 URL,而不受配置的嵌套结构的限制。使别名以 / 开头,以使嵌套路径中的路径成为绝对路径。你甚至可以将两者结合起来,用一个数组提供多个别名:
const routes = [
{
path: '/users',
component: UsersLayout,
children: [
// 为这 3 个 URL 呈现 UserList
// - /users
// - /users/list
// - /people
{ path: '', component: UserList, alias: ['/people', 'list'] },
],
},
]
如果你的路由有参数,请确保在任何绝对别名中包含它们:
const routes = [
{
path: '/users/:id',
component: UsersByIdLayout,
children: [
// 为这 3 个 URL 呈现 UserDetails
// - /users/24
// - /users/24/profile
// - /24
{ path: 'profile', component: UserDetails, alias: ['/:id', ''] },
],
},
]