一、hash模式与history模式的实现原理
1. hash模式
原理:通过window.location.hash获取到当前url的hash;hash模式下通过hashchange方法可以监听url中hash的变化 hash模式是vue-router的默认路由模式,它的标志是在域名之后带有一个#
http://localhost:8888/#/home
* 通过window.location.hash获取到当前url的hash;
eg:let path = window.location.hash || "#1"
* 通过a标签或者location.assign(url)进行页面切换例如:
<a href="#1" @click="change">去1号组件</a>
document.location.assign('https://developer.mozilla.org/zh-CN/docs/Web/API/Location/reload');
* hash模式下通过hashchange方法可以监听url中hash的变化
window.removeEventListener("hashchange", this.route,false)
window.addEventListener("hashchange", this.route,false)
2.history模式
原理:通过location.pathname获取到当前url的路由地址;history模式下,通过pushState和replaceState方法可以修改url地址,结合popstate方法监听url中路由的变化 history模式下的路由更加美观
http://localhost:8888/home
*通过location.pathname获取到当前url的路由地址;
let path = window.location.pathname || "/1"
*history模式下,通过pushState和replaceState方法可以修改url地址,
<a href="/1" @click.prevent="change">去1号组件</a>
const change=(e)=> {
window.history.pushState(null,"page1",e.target.getAttribute("href"))
path = window.location.pathname
console.log(path)
Component = RouteTable[path.toString()]
if (!Component) {
component.value = 'Component404'
} else {
component.value = RouteTable[path.toString()]
}
},
二、vue-router
1.创建路由并挂载
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes,
})
const app = Vue.createApp({})
app.use(router)
app.mount('#app')
2.组件内使用路由
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<router-view></router-view>
</div>
3.动态路由
{ path: '/users/:id', component: User },
组件内通过route.params.id 获取路由id的参数
4. 404路由
const routes = [
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },
{ path: '/user-:afterUser(.*)', component: UserGeneric },
]
5. 路由匹配
const routes = [
在参数中自定义正则
{ path: '/:orderId(\\d+)' },
{ path: '/:productName' },
可重复的参数
{ path: '/:chapters+' },
{ path: '/:chapters*' },
可重复的参数
{ path: '/:chapters(\\d+)+' },
{ path: '/:chapters(\\d+)*' },
可选参数
{ path: '/users/:userId?' },
{ path: '/users/:userId(\\d+)?' },
]
6.导航到不同的位置
api router.push(...) 注意:如果提供了 path,params 会被忽略,上述例子中的 query 并不属于这种情况。你需要提供路由的 name 或手写完整的带有参数的 path :
router.push({ path: '/users/eduardo' })
router.push({ name: 'user', params: { username } })
router.push({ path: '/register', query: { plan: 'private' } })
router.replace(...) 它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。
router.push({ path: '/home', replace: true })
router.replace({ path: '/home' })
router.go(...)
router.go(1)
router.go(-1)
router.go(3)
7.命名路由
const routes = [
{
path: '/user/:username',
name: 'user',
component: User
}
]
<router-link :to="{ name: 'user', params: { username: 'erina' }}">
User
</router-link>
router.push({ name: 'user', params: { username: 'erina' } })
8.命名视图
如果 router-view 没有设置名字,那么默认为 default
const router = createRouter({
history: createWebHashHistory(),
routes: [
{
path: '/',
components: {
default: Home,
LeftSidebar:LeftSidebar,
RightSidebar:LeftSidebar,
},
},
],
})
<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>
9.重定向和别名
redirect 重定向是指当用户访问 /home 时,URL 会被 / 替换,然后匹配成 /
const routes = [
{ path: '/home', redirect: '/' },
{
path: '/search/:searchText',
redirect: to => {
return { path: '/search', query: { q: to.params.searchText } }
},
},
]
alias 将 / 别名为 /home,意味着当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /。
const routes = [
{ path: '/', component: Homepage, alias: '/home' },
{
path: '/users',
component: UsersLayout,
children: [
{ path: '', component: UserList, alias: ['/people', 'list'] },
],
},
]
10.导航守卫
to: 即将要进入的目标 用一种标准化的方式 from: 当前导航正要离开的路由 用一种标准化的方式
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
完整的导航解析流程
导航被触发。
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫(2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
10.路由元信息
有时,你可能希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等。这些事情可以通过接收属性对象的meta属性来实现,并且它可以在路由地址和导航守卫上都被访问到。定义路由的时候你可以这样配置 meta 字段:
const routes = [
{
path: '/posts',
component: PostsLayout,
children: [
{
path: 'new',
component: PostsNew,
meta: { requiresAuth: true }
},
{
path: ':id',
component: PostsDetail
meta: { requiresAuth: false }
}
]
}
]
router.beforeEach((to, from) => {
if (to.meta.requiresAuth && !auth.isLoggedIn()) {
return {
path: '/login',
query: { redirect: to.fullPath },
}
}
})
11.过渡动效
<router-view v-slot="{ Component }">
<transition name="fade">
<component :is="Component" />
</transition>
</router-view>
上面的用法会对所有的路由使用相同的过渡。如果你想让每个路由的组件有不同的过渡,你可以将元信息和动态的 name 结合在一起,放在 上
const routes = [
{
path: '/custom-transition',
component: PanelLeft,
meta: { transition: 'slide-left' },
},
{
path: '/other-transition',
component: PanelRight,
meta: { transition: 'slide-right' },
},
]
<router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition || 'fade'">
<component :is="Component" />
</transition>
</router-view>
滚动
注意: 这个功能只在支持 history.pushState 的浏览器中可用。 使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。 如果返回一个 falsy 的值,或者是一个空对象,那么不会发生滚动。
const router = createRouter({
history: createWebHashHistory(),
routes: [...],
scrollBehavior (to, from, savedPosition) {
return { top: 0 }
}
})
路由懒加载
const UserDetails = () => import('./views/UserDetails')
const router = createRouter({
routes: [{ path: '/users/:id', component: UserDetails }],
})
三、
github链接 router
|