文章目录
1. 引言
路由元信息类似鉴权,如果有些页面,不想用刚刚上一篇我们所写的savedPosition
效果,如除了详情页,其他页面点击前进和后退都顶到头,这个时候怎么做呢?
如果死板地去一个一个判断,是非常麻烦的。
判断如果当前to
的目标是view
,像我们的例子,只有一个页面,还好说,如果上百个页面就没办法解决了。
因此我们可以利用路由元信息进行标注 ,它实际和标签自定义属性是一样的,这里实际就是路由的自定义属性。
2. 路由元信息
定义路由的时候可以配置 meta
字段
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
// a meta field
meta: {
requiresAuth: true }
}
]
}
]
})
那么如何访问这个 meta
字段呢?
首先,我们称呼 routes
配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录
例如,根据上面的路由配置,/foo/bar
这个 URL
将会匹配父路由记录以及子路由记录。
一个路由匹配到的所有路由记录会暴露为 $route
对象 (还有在导航守卫中的路由对象) 的 $route.matched
数组。因此,我们需要遍历 $route.matched
来检查路由记录中的 meta
字段。
下面例子展示在全局导航守卫中检查元字段:
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!auth.loggedIn()) {
next({
path: '/login',
query: {
redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // 确保一定要调用 next()
}
})
3. 通过 meta
定义要验证的路由
const router = new Router({
routes: [
{
path: '/user',
component: User,
children: [
{
path: '',
name: 'user',
component: Profile,
meta: {
requiresAuth: true }
},
{
path: 'cart',
name: 'user-cart',
component: Cart,
meta: {
requiresAuth: true }
}
]
}
]
})
const isLogin = true;
router.beforeEach((to, from, next) => {
NProgress.start()
if (to.meta.requiresAuth && !isLogin) {
next({
name: 'login',
})
} else {
next()
}
})
或者
const router = new Router({
routes: [
{
path: '/user',
component: User,
meta: {
requiresAuth: true }
children: [
{
path: '',
name: 'user',
component: Profile
},
{
path: 'cart',
name: 'user-cart',
component: Cart
}
]
}
]
})
const isLogin = true;
router.beforeEach((to, from, next) => {
NProgress.start()
if (to.matched.some(record => record.meta.requiresAuth) && !isLogin) {
next({
name: 'login',
})
} else {
next()
}
})
4. 实例
4.1 example01
实现除了详情页,其他页面点击前进和后退都顶到头。
路由下每个页面的meta
属性,里面的值,随意定。 =>
定好之后我们就可以在scrollBehavior
中进行判断了,如果当前页面的to
下的meta
属性下的该值为真就往下走。
\app\src\router\index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '@/views/Home';
import About from '@/views/About';
import Detail from '@/views/Detail';
Vue.use(VueRouter);
let router = new VueRouter({
mode: 'history',
scrollBehavior(to, from, savedPosition) {
console.log(savedPosition);
if (to.meta.isToSavedPosition && savedPosition) {
// 调用的浏览器的历史记录
return savedPosition;
}
return {
x: 0,
y: 0
}
},
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
},
{
path: '/view',
name: 'view',
component: Detail,
meta: {
isToSavedPosition: true}
}
]
});
export default router;
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.32
Branch: branch07commit description:a2.32(example01-1——初步实现除了详情页,其他页面点击前进和后退都顶到头)
tag:a2.32
4.2 example02
通过以上这种方式 ,就可以判断当前页面后退的时候,到底是重置为0
呢?还是保持原来的位置?
如果我们运用原生逻辑判断的方式,会十分的麻烦,这个时候就可以把信息记录在路由原元信息
当中了,在路由中通过to
、from
这些参数拿到对应自定义的元信息
了,进行处理。
比如有很多的菜单,即页面当中必然有一些导航,这个时候我们会发现,我们有一种办法通过这种路由的方式去动态生成导航,这里有三个页面,我们动态生成三个导航。
4.2.1 example02-1
加isNav
,说明此页面到底加不加导航链接。
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
},
{
path: '/view',
name: 'view',
component: Detail,
meta: {
isToSavedPosition: true, isNav: true }
}
]
app\src\views\Home.vue
<template>
<div>
<nav>
<div v-for="nav of navs">
<router-link :to="nav.path">{
{nav.name}}</router-link>
<span> | </span>
</div>
</nav>
<hr>
<ul>
<li v-for="i of 100">{
{i}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
navs: []
}
},
created() {
console.log(this.$router);
// this.$router.options.routes 所有路由的信息
this.navs = this.$router.options.routes;
}
}
</script>
<style>
</style>
如果不希望动态生成 =>
meta: {
isToSavedPosition: true, isNav: false }
然后在created
中进行过滤
<template>
<div>
<nav>
<div v-for="nav of navs">
<router-link :to="nav.path">{
{nav.name}}</router-link>
<span> | </span>
</div>
</nav>
<hr>
<ul>
<li v-for="i of 100">{
{i}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
navs: []
}
},
created() {
console.log(this.$router);
// this.$router.options.routes 所有路由的信息
// this.navs = this.$router.options.routes;
this.navs = this.$router.options.routes.filter(route => {
// 无meta标签
if (route.meta === undefined) {
return true;
}
// 有meta标签 => 需要显示就显示
if (route.meta.isNav === true) {
return true;
}
});
}
}
</script>
<style>
</style>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.33
Branch: branch07commit description:a2.33(example02-1——动态生成子导航)
tag:a2.33
4.2.2 example02-2
有的时候name
并不想显示英文,meta
加一个中文属性。
meta
这个元数据,其实存放与本质数据无关的旁观数据,就和我们的标签的自定义属性一样,主要挂载一些不太重要的数据。
routes: [
{
path: '/',
name: 'home',
component: Home,
meta: {
navName: '首页' }
},
{
path: '/about',
name: 'about',
component: About,
meta: {
navName: '关于我们' }
},
{
path: '/view',
name: 'view',
component: Detail,
meta: {
isToSavedPosition: true, isNav: false, navName: '视图' }
}
]
\app\src\views\Home.vue
<template>
<div>
<nav>
<div v-for="nav of navs">
<router-link :to="nav.path">{
{nav.meta.navName}}</router-link>
<span> | </span>
</div>
</nav>
<hr>
<ul>
<li v-for="i of 100">{
{i}}</li>
</ul>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
navs: []
}
},
created() {
console.log(this.$router);
// this.$router.options.routes 所有路由的信息
// this.navs = this.$router.options.routes;
this.navs = this.$router.options.routes.filter(route => {
// 无meta标签
if (route.meta === undefined || route.meta.isNav === undefined) {
return true;
}
// 有meta标签 => 需要显示就显示
if (route.meta.isNav === true) {
return true;
}
});
}
}
</script>
<style>
</style>
参考:https://https://github.com/6xiaoDi/blog-vue-Novice/tree/a2.34
Branch: branch07commit description:a2.34(example02-2——动态生成子导航附加中文)
tag:a2.34
考虑到在blog中不好体现代码更改的位置,小迪才用github托管代码,大家可以查看github,看到详细版本修改过程,搭配博客学习。
(后续待补充)