Vue3复习和总结----vue-router
Vue3复习和总结(vue-router)代码全部放在->github仓库:https://github.com/zyugat/vue-review-all前言:分为base、Component、router、Vuex、组合式API。5个部分。base和Component中的例子不使用脚手架运行,需自行浏览器运行。位置->noClivue-routerVue3复习和总结(vue-rou
Vue3复习和总结(vue-router)
代码全部放在->github仓库:https://github.com/zyugat/vue-review-all
前言:分为base、Component、router、Vuex、组合式API。5个部分。
base和Component中的例子不使用脚手架运行,需自行浏览器运行。位置->noCli
router目录:router/index.js
、页面:views
当切换页面时,是直接销毁页面
创建router流程:创建router/index.js
文件编写配置,创建router-link
标签用于跳转页面,创建router-view
用于显示对应组件。
目录:
base
- router-link:链接;router-view:显示URL对应组件;children:嵌套路由
路由传参
- params、query
路由匹配正则
- 匹配所有内容、匹配xxx开头内容、可重复次数、可选参数
命名路由与视图
- 命名路由:
name
属性;命名视图:同时/同级展示多个视图重定向和别名和props
- 重定向:
redirect
、别名:alias
- props四种模式:布尔模式、命名视图、对象模式、函数模式
导航守卫
- 全局前置守卫、全局解析守卫、全局后置守卫、路由独享守卫
- 渲染组件前守卫、组件复用时守卫、离开组件时守卫
元信息
- 获取meta字段:
$router.meta
(过渡名称、谁可以访问路由)滚动行为
scrollBehavior(to, from, savedPosition){return{}}
el
传递CSS选择器或DOM元素、返回savedPosition
视为像原生浏览器前进后退、滚动到锚点、延迟滚动补
- router和route区别、懒加载
- 路由跳转命令、Hash模式、HTML5模式
- 数据获取:导航完成后获取数据、在导航完成前获取数据
- 组件内容传递:必须使用
v-slot
API 将其传递给<component>
router-link
创建一个链接
tag
:指定渲染成任意组件
replace
:页面跳转的时候禁止返回
active-class
:对应的路由匹配成功时, 会自动给当前元素设置class
<router-link to="/test1" tag="button" replace active-class="my-active">test1</router-link>
// router/index.js
const router = createRouter({
history: createWebHistory(),
routes,
linkActiveClass: 'my-active'
})
router-view
显示与url对应的组件。
<router-view></router-view>
router/index.js
// 1. 定义路由组件.
// 也可以从其他文件导入
// import Home from '../components/Home'
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = VueRouter.createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: VueRouter.createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
// 5. 创建并挂载根实例
const app = Vue.createApp({})
//确保 _use_ 路由实例使
//整个应用支持路由。
app.use(router)
app.mount('#app')
嵌套路由:使用:children:[{...},{...}]
{
path: '/test1',
name: 'test1',
component: () => import('../components/home'),
children: [
{
path: '',
// 重定向
redirect: '/test1/children1'
},
{
path: 'children1',
component: () => import('../components/children1')
},
{
path: 'children2',
component: () => import('../components/children2')
}
]
}
路由传参
如果使用带参数的路由,从api/123
到api/321
,因为使用相同的组件实例所以会被复用。意味着生命周期钩子不会被调用。
params
:修改路由地址:path:'/params/:abc'
query
:修改跳转链接::to="{ path: '/api', query: { name: '我是query数据' } }"
<template>
<h2>Api</h2>
<p>路由传参 params:{{ $route.params.abc }}</p>
<p>路由传参 query:{{ $route.query.name }}</p>
</template>
<div id="router">
<router-link to="/api/我是params数据">Api-路由传参params</router-link
><br />
<router-link :to="{ path: '/api', query: { name: '我是query数据' } }">
Api-query
</router-link>
</div>
const routes = [
{ path: '/api', component: () => import('../views/api') },
{ path: '/api/:abc', component: () => import('../views/api') },
]
路由匹配正则
在括号中加入正则表达式
1、将匹配所有内容:path: '/:pathMatch(.*)'
,并将其放在 $route.params.pathMatch
下
2、匹配user-开头的路由:path: '/user-:afterUser(.*)'
,并将匹配内容放在$route.params.afterUser
下
3、可重复参数:path: '/user-:afterUser(.*)*'
,最后面加了一个*
,意思是会匹配后续所有->user-123456/123/456
,返回值是数组。(*
->0个或多个。+
->1个或多个)
4、可选:?
,0个或1个
{ path: '/:pathMatch(.*)', component: () => import('../views/api') },
{ path: '/user-:afterUser(.*)', component: () => import('../views/api') },
{ path: '/user-:afterUser(.*)*', component: () => import('../views/api') },
<p>路由匹配正则表达式 /:pathMatch(.*):{{ $route.params.pathMatch }}</p>
<p>路由匹配正则表达式 /user-:afterUser(.*):{{ $route.params.afterUser }}</p>
命名路由与视图
命名路由:name
- 没有硬编码的 URL
params
的自动编码/解码。- 防止你在 url 中出现打字错误。
- 绕过路径排序(如显示一个)
router.push({ name: 'user', params: { username: 'erina' } })
const routes = [
{
path: '/user/:username',
name: 'user',
component: User
}
]
<router-link :to="{ name: 'user', params: { username: 'erina' }}">
User
</router-link>
命名视图
同时/同级展示多个视图。不是嵌套。
例子中:我希望main组件一直都在中间,切换路由时我希望Left与Right交换位置。
{
path: '/nameLeft',
components: {
default: left,
main,
change: right,
},
},
{
path: '/nameRight',
components: {
default: right,
main,
change: left,
},
},
<router-link to="/nameLeft">left</router-link>——————
<router-link to="/nameRight">Right</router-link>
<router-view />
<router-view name="main" />
<router-view name="change" />
重定向和别名和props
重定向:redirect
const routes = [{ path: '/home', redirect: '/' }]
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]
{
// /search/screens -> /search?q=screens
path: '/search/:searchText',
redirect: to => {
// 方法接收目标路由作为参数
// return 重定向的字符串路径/路径对象
return { path: '/search', query: { q: to.params.searchText } }
},
},
别名:alias:''
当访问/home时也是访问/页面。
const routes = [{ path: '/', component: Homepage, alias: '/home' }]
开启Props:props: true
props分为四种模式:布尔模式、命名视图、对象模式、函数模式
在路由组件中我们一般是:$route.params.id
,获取到属性。现在我们只需要使用props
即可。
1、布尔模式
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
}
const routes = [{ path: '/user/:id', component: User, props: true }]
2、命名视图:则需要为每个命名视图定义一个props
配置
const routes = [
{
path: '/user/:id',
components: { default: User, sidebar: Sidebar },
props: { default: true, sidebar: false }
}
]
3、对象模式:
props: { newsletterPopup: false }
4、函数模式:用于将参数转换为其他类型
例如:URL/search?q=vue
将传递{query: 'vue'}
作为props传为组件。
props: route => ({ query: route.query.q })
导航守卫
要注意,全局守卫是写在vue-router文件里面
守卫有next,钩子没有。
全局守卫有三个:
router.beforeEach
全局前置守卫、router.beforeResolve
全局解析守卫、router.afterEach
全局后置钩子
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。- 调用全局的
router.beforeEach
守卫。- 在重用的组件里调用
beforeRouteUpdate
守卫 (2.2+)。- 在路由配置里调用
beforeEnter
。- 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。- 调用全局的
router.beforeResolve
守卫 (2.5+)。- 导航被确认。
- 调用全局的
router.afterEach
钩子。- 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
to: Route
: 即将要进入的目标路由对象from: Route
: 当前导航正要离开的路由next: Function
: 一定要调用该方法来 resolve 这个钩子。执行效果依赖next
方法的调用参数。next()
:执行下一个钩子next(false)
:中断当前的导航next('/')
或next({path: '/'})
:跳转不同导航next(error)
:传入一个Error的实例,导航会被中断且传递错误给router.onError()
注册过的回调
路由流程:
router.beforeEach(to, from, next)
:全局前置守卫
跳转路由之前都会调用这个回调。
router.beforeResolve(to, from, next)
:全局解析守卫
是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
router.afterEach(to, from)
:全局后置钩子
路由跳转后的回调。没有next就无法改变导航本身,故用于分析、更改页面标题、声明页面等辅助功能。
beforeEnter(to, from, next)
:路由独享的守卫
只在进入路由时触发,不会在 params
、query
或 hash
改变时触发,在路由配置上直接定义。
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
组件内部守卫:
beforeRouteEnter(to, from, next)
:渲染组件前。
不能访问组件实例 this
,因为实例还未创建
beforeRouteUpdate(to, from, next)
:组件复用时。
可以访问组件实例 this
beforeRouteLeave(to, from, next)
:离开组件时。
可以访问组件实例 this
元信息
过渡名称、谁可以访问路由等,可以使用meta
属性实现。
const routes = [
{
path: '/posts',
component: PostsLayout,
children: [
{
path: 'new',
component: PostsNew,
// 只有经过身份验证的用户才能创建帖子
meta: { requiresAuth: true }
},
{
path: ':id',
component: PostsDetail,
// 任何人都可以阅读文章
meta: { requiresAuth: false }
}
]
}
]
1、首先 routers
配置中每个路由对象为 路由记录,根据上面的路由配置,/foo/bar
这个 URL 将会匹配父路由记录以及子路由记录。
2、路由匹配到的所有路由记录会暴露为:$route
对象的 $route.matched
数组。(第四行)
3、通过遍历数组检测路由记录的 meta
字段。但是Vue Router中可以使用 $route.meta
,非递归合并所有 meta 字段的(从父字段到子字段)的方法。
总结:通过$router.meta
获取meta字段
// to: 即将进入的路由对象
router.beforeEach((to, from) => {
// 而不是去检查每条路由记录
// to.matched.some(record => record.meta.requiresAuth)
if (to.meta.requiresAuth && !auth.isLoggedIn()) {
// 此路由需要授权,请检查是否已登录
// 如果没有,则重定向到登录页面
return {
path: '/login',
// 保存我们所在的位置,以便以后再来
query: { redirect: to.fullPath },
}
}
})
滚动行为
const router = createRouter({
history: createWebHashHistory(),
routes: [...],
scrollBehavior(to, from, savedPosition) {
// 始终滚动到顶部
return { top: 0 }
},
})
2、通过 el
传递CSS选择器或DOM元素,top和left视为偏移量
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
// 始终在元素 #main 上方滚动 10px
return {
// 也可以这么写
// el: document.getElementById('main'),
el: '#main',
top: -10,
}
},
})
3、返回false值或空对象则不变化,返回 savedPosition
,在按下 后退/前进 按钮时,就会像浏览器的原生表现那样:
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
},
})
4、滚动到锚点:
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
el: to.hash,
}
}
},
})
5、延迟滚动,返回一个Promise
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ left: 0, top: 0 })
}, 500)
})
},
})
补
router与route区别
router是指向Vue实例的router,而route他永远是指向当前活跃的对象,当按钮被点击时(此时按钮正处于活跃),就返回按钮信息。
懒加载,把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件:const home = () => import('../components/home')
同时component
(和 components
) 配置接收一个返回 Promise 组件的函数,Vue Router 只会在第一次进入页面时才会获取这个函数,然后使用缓存数据。
const UserDetails = () =>
Promise.resolve({
/* 组件定义 */
})
路由跳转:this.$router.push('/')
Hash模式:history: createWebHashHistory(),
HTML5模式:history: createWebHistory(),
数据获取
1、导航完成后获取数据:在created
钩子中创建watch
监听this.$route.params
路由属性。当发送改变时获取数据。
2、在导航完成前获取数据:在beforeRouteEnter
守卫(渲染组件前调用),中获取数据。
beforeRouteEnter (to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// 路由改变前,组件就已经渲染完了
// 逻辑稍稍不同
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
组件内容传递
你必须使用 v-slot
API 将其传递给 <component>
<router-view v-slot="{ Component }">
<component :is="Component">
<p>In Vue Router 3, I render inside the route component</p>
</component>
</router-view>
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)