前端【VUE】07-vue【路由】【声明式导航【导航高亮-精确匹配和模糊匹配】【自定义高亮类名】【导航传参】】【编程式导航【导航传参【查询参数传参、动态路由传参】】】【路由守卫】

一、路由

单页应用程序: SPA - Single Page Application

  

  

 

 

VueRouter 的 介绍

  作用:修改地址栏路径时,切换显示匹配的组件
  说明:Vue 官方的一个路由插件,是一个第三方包
  官网:https://v3.router.vuejs.org/zh/
  vue2 对应  router3 
  vue3 对应 router4

 

  1、如果配置了二级路由,则访问二级路由时就是使用:  一级路由/二级路由 

 1   {
 2     path: '/park',
 3     component: Layout,
 4     permission: 'park',
 5     meta: { title: '园区管理', icon: 'el-icon-office-building' },
 6     children: [
 7       {
 8         path: 'building', // 访问: 二级路由   /park/building
 9         permission: 'park:building',
10         meta: { title: '楼宇管理' },
11         component: () => import('@/views/Park/Building/index')
12       },
13       {
14         path: 'enterprise', // /park/enterprise
15         permission: 'park:enterprise',
16         meta: { title: '企业管理' },
17         component: () => import('@/views/Park/Enterprise/index')
18       }
19     ]
20   }

  2、如果配置了二级路由,但是二级路由的path为'', 此时访问一级路由,就相当于访问二级路由

 1   {
 2     path: '/workbench',
 3     component: Layout,
 4     children: [
 5       {
 6         path: '',
 7         component: () => import('@/views/Workbench/index'),
 8         meta: { title: '工作台', icon: 'el-icon-data-board' }
 9       }
10     ]
11   }

 

  通过注入路由器,我们可以在任何组件内通过 this. r o u t e r 访 问 路 由 器 , 也 可 以 通 过 t h i s . router 访问路由器,也可以通过 this. router访问路由器,也可以通过this.route 访问当前路由.

    

  

  通过打印出: this.$router 和 this. $route :
    this.$router(路由实例) : 是VueRouter的实例.包含了很多属性和对象(比如 history 对象),任何页面都可以调用其 push(), replace(), go() 等方法。
    this.$route: 表示当前路由对象,每一个路由都会有一个 route 对象,是一个局部的对象,可以获取对应的 name, path, meta, params, query 等属性。

 1 $route.path
 2 类型: string
 3 字符串,对应当前路由的路径,总是解析为绝对路径,如 /foo/bar。
 4 
 5 $route.params
 6 类型: Object
 7 一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象。
 8 
 9 $route.query
10 类型: Object
11 一个key/value 对象,表示 URL 查询参数。例如,对于路径/foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。
12 
13 $route.matched
14 类型:Array
15 一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。
16 $route.fullPath
17 路由是:/path/:type真正路径是:/path/list
18 path匹配路径: /path/list
19 fullPath匹配路由: /path/:type
20 
21 $route.meta (路由原信息meta)
22 const router = new VueRouter({
23   routes: [
24     {
25       path: '/foo',
26       component: Foo,
27       children: [
28         {
29           path: 'bar',
30           component: Bar,
31           // a meta field
32           meta: { requiresAuth: true ,keepAlive:true}//1.权限 2.内存缓存,单页面切换
33         }
34       ]
35     }
36   ]
37 })
38 
39 $route.matched
40 一个数组,包含当前路由的所有嵌套路径片段的路由记录
41 一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的 $route.matched 数组
42 
43 路由元信息 .meta $route.matched 搭配路由守卫 进行验证
44 router.beforeEach((to, from, next) => {
45   if (to.matched.some(record => record.meta.requiresAuth)) {
46     // this route requires auth, check if logged in
47     // if not, redirect to login page.
48     if (!auth.loggedIn()) {
49       next({
50         path: '/login',
51         query: { redirect: to.fullPath }
52       })
53     } else {
54       next()
55     }
56   } else {
57     next() // 确保一定要调用 next()
58   }
59 })

  获取当前页面的路由:

1 this.$route.fullPath

 

 


 

  1、正常导入方式

 1 import Vue from 'vue'
 2 import VueRouter from 'vue-router'
 3 import { getToken } from '@/utils/storage'
 4 // 导入路由
 5 import Login from '@/views/Layout'
 6 import Register from '@/views/Register'
 7 import Article from @/views/Article'
 8 import Collect from '@/views/Collect'
 9 
10 Vue.use(VueRouter)
11 
12 const router = new VueRouter({
13   // 注册路由
14   routes: [
15     { path: '/login', component: Login },
16     { path: '/register', component: Register },
17     {
18       path: '/',
19       component: Layout,
20       redirect: '/article',
21       children: [
22         { path: '/article', component: Article },
23         { path: '/collect', component: Collect },
24       ]
25     }
26   ]
27 })
28 
29 // 白名单(就是一个数组,数组收录所有无需登录即可访问的页面)
30 const whiteList = ['/login', '/register']
31 
32 // 路由前置守卫
33 // 1. to 往哪去
34 // 2. from 从哪来
35 // 3. next 是否放行 next() 放行 next(路径) 拦截到某个页面
36 router.beforeEach((to, from, next) => {
37   const token = getToken()
38   if (token) {
39     // 如果有token,直接放行
40     next()
41   } else {
42     // 没有token的人,看看要去哪
43     // 判断访问的路径 to.path, 是否在白名单中
44     if (whiteList.includes(to.path)) {
45       next()
46     } else {
47       next('/login')
48     }
49   }
50 })
51 
52 export default router

  2、通过箭头函数导入组件

 1 import Vue from 'vue'
 2 import VueRouter from 'vue-router'
 3 import { getToken } from '@/utils/storage'
 4 import Login from '@/views/Layout.vue'
 5 
 6 // 一级路由页面的导入
 7 const Login = () => import('@/views/Login')
 8 const Register = () => import('@/views/Register')
 9 const Layout = () => import('@/views/Layout')
10 const Detail = () => import('@/views/Detail')
11 
12 Vue.use(VueRouter)
13 
14 const router = new VueRouter({
15   routes: [
16     { path: '/login', component: Login },
17     { path: '/register', component: Register },
18     // 动态路由传参的方式
19     { path: '/article/:id', component: Detail },
20     {
21       path: '/',
22       component: Layout,
23       redirect: '/article',
24       children: [
25         { path: '/article', component: () => import('@/views/Article') },
26         { path: '/like', component: () => import('@/views/Like') },
27         { path: '/collect', component: () => import('@/views/Collect') },
28         { path: '/user', component: () => import('@/views/User') }
29       ]
30     }
31   ]
32 })
33 
34 // 白名单(就是一个数组,数组收录所有无需登录即可访问的页面)
35 const whiteList = ['/login', '/register']
36 
37 // 路由前置守卫
38 // 1. to 往哪去
39 // 2. from 从哪来
40 // 3. next 是否放行 next() 放行 next(路径) 拦截到某个页面
41 router.beforeEach((to, from, next) => {
42   const token = getToken()
43   if (token) {
44     // 如果有token,直接放行
45     next()
46   } else {
47     // 没有token的人,看看要去哪
48     // 判断访问的路径 to.path, 是否在白名单中
49     if (whiteList.includes(to.path)) {
50       next()
51     } else {
52       next('/login')
53     }
54   }
55 })
56 
57 export default router

 

VueRouter 的 使用

  

  

1、下载

1 npm  i  vue-router@3.6.5

2、项目中新增views目录,存放各个视图页面

views/Find.vue

 1 <template>
 2   <div>
 3     <p>我的音乐</p>
 4     <p>我的音乐</p>
 5     <p>我的音乐</p>
 6     <p>我的音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyMusic'
13 }
14 </script>
15 <style>
16 </style>

views/Friend.vue

 1 <template>
 2   <div>
 3     <p>我的朋友</p>
 4     <p>我的朋友</p>
 5     <p>我的朋友</p>
 6     <p>我的朋友</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyFriend'
13 }
14 </script>
15 <style>
16 </style>

views/My.vue

 1 <template>
 2   <div>
 3     <p>我的音乐</p>
 4     <p>我的音乐</p>
 5     <p>我的音乐</p>
 6     <p>我的音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyMusic'
13 }
14 </script>
15 <style>
16 </style>

3、根组件App.vue中添加路由出口,也就是用来路由到不同视图的位置

 1 <template>
 2   <div>
 3     <div class="footer_wrap">
 4       <a href="#/find">发现音乐</a>
 5       <a href="#/my">我的音乐</a>
 6       <a href="#/friend">朋友</a>
 7     </div>
 8     <div class="top">
 9       <!-- 路由出口 → 匹配的组件所展示的位置 -->
10       <router-view></router-view>
11     </div>
12   </div>
13 </template>
14 
15 <script>
16 export default {};
17 </script>
18 
19 <style>
20 body {
21   margin: 0;
22   padding: 0;
23 }
24 .footer_wrap {
25   position: relative;
26   left: 0;
27   top: 0;
28   display: flex;
29   width: 100%;
30   text-align: center;
31   background-color: #333;
32   color: #ccc;
33 }
34 .footer_wrap a {
35   flex: 1;
36   text-decoration: none;
37   padding: 20px 0;
38   line-height: 20px;
39   background-color: #333;
40   color: #ccc;
41   border: 1px solid black;
42 }
43 .footer_wrap a:hover {
44   background-color: #555;
45 }
46 </style>

4、main.js中定义路由,并且注册到vue实例中,后续写项目会将路由单独写到router目录下index.js中,通过export导出定义的路由组件,然后在main.js中导入定义的路由进行注册

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 
 4 // 路由的使用步骤 5 + 2
 5 // 5个基础步骤
 6 // 1. 下载 v3.6.5
 7 // 2. 引入
 8 // 3. 安装注册 Vue.use(Vue插件)
 9 // 4. 创建路由对象
10 // 5. 注入到new Vue中,建立关联
11 
12 // 2个核心步骤
13 // 1. 建组件(views目录),配规则
14 // 2. 准备导航链接,配置路由出口(匹配的组件展示的位置) 
15 import Find from './views/Find'
16 import My from './views/My'
17 import Friend from './views/Friend'
18 import VueRouter from 'vue-router'
19 Vue.use(VueRouter) // VueRouter插件初始化
20 
21 const router = new VueRouter({
22   // routes 路由规则们
23   // route  一条路由规则 { path: 路径, component: 组件 }
24   routes: [
25     { path: '/find', component: Find },
26     { path: '/my', component: My },
27     { path: '/friend', component: Friend },
28   ]
29 })
30 
31 Vue.config.productionTip = false
32 
33 new Vue({
34   render: h => h(App),
35   router
36 }).$mount('#app')

组件存放目录问题

  

路由的封装抽离

  

 1、目录结构

  

2、路由目录

  router/index.js

 1 import Find from '@/views/Find'
 2 import My from '@/views/My'
 3 import Friend from '@/views/Friend'
 4 
 5 import Vue from 'vue'
 6 import VueRouter from 'vue-router'
 7 Vue.use(VueRouter) // VueRouter插件初始化
 8 
 9 // 创建了一个路由对象
10 const router = new VueRouter({
11   // routes 路由规则们
12   // route  一条路由规则 { path: 路径, component: 组件 }
13   routes: [
14     { path: '/find', component: Find },
15     { path: '/my', component: My },
16     { path: '/friend', component: Friend },
17   ]
18 })
19 
20 export default router

3、视图目录

views/Find.vue

 1 <template>
 2   <div>
 3     <p>发现音乐</p>
 4     <p>发现音乐</p>
 5     <p>发现音乐</p>
 6     <p>发现音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'FindMusic'
13 }
14 </script>
15 <style>
16 </style>

views/Friend.vue

 1 <template>
 2   <div>
 3     <p>我的朋友</p>
 4     <p>我的朋友</p>
 5     <p>我的朋友</p>
 6     <p>我的朋友</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyFriend'
13 }
14 </script>
15 <style>
16 </style>

views/My.vue

 1 <template>
 2   <div>
 3     <p>我的音乐</p>
 4     <p>我的音乐</p>
 5     <p>我的音乐</p>
 6     <p>我的音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyMusic'
13 }
14 </script>
15 <style>
16 </style>

4、根组件App.vue

 1 <template>
 2   <div>
 3     <div class="footer_wrap">
 5       <a href="#/find">发现音乐</a>
 6       <a href="#/my">我的音乐</a>
 7       <a href="#/friend">朋友</a>
 8     </div>
 9     <div class="top">
10       <!-- 2、路由出口 → 匹配的组件所展示的位置 -->
11       <router-view></router-view>
12     </div>
13   </div>
14 </template>
15 
16 <script>
17 export default {};
18 </script>
19 
20 <style>
21 body {
22   margin: 0;
23   padding: 0;
24 }
25 .footer_wrap {
26   position: relative;
27   left: 0;
28   top: 0;
29   display: flex;
30   width: 100%;
31   text-align: center;
32   background-color: #333;
33   color: #ccc;
34 }
35 .footer_wrap a {
36   flex: 1;
37   text-decoration: none;
38   padding: 20px 0;
39   line-height: 20px;
40   background-color: #333;
41   color: #ccc;
42   border: 1px solid black;
43 }
44 .footer_wrap a:hover {
45   background-color: #555;
46 }
47 </style>

5、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

 声明式导航 - 导航链接

  

 1、router目录下index.js

 1 import Find from '@/views/Find'
 2 import My from '@/views/My'
 3 import Friend from '@/views/Friend'
 4 
 5 import Vue from 'vue'
 6 import VueRouter from 'vue-router'
 7 Vue.use(VueRouter) // VueRouter插件初始化
 8 
 9 // 创建了一个路由对象
10 const router = new VueRouter({
11   // routes 路由规则们
12   // route  一条路由规则 { path: 路径, component: 组件 }
13   routes: [
14     { path: '/find', component: Find },
15     { path: '/my', component: My },
16     { path: '/friend', component: Friend },
17   ]
18 })
19 
20 export default router

2、视图目录下

views/Find.vue

 1 <template>
 2   <div>
 3     <p>发现音乐</p>
 4     <p>发现音乐</p>
 5     <p>发现音乐</p>
 6     <p>发现音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'FindMusic'
13 }
14 </script>
15 <style>
16 </style>

views/Friend.vue

 1 <template>
 2   <div>
 3     <p>我的朋友</p>
 4     <p>我的朋友</p>
 5     <p>我的朋友</p>
 6     <p>我的朋友</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyFriend'
13 }
14 </script>
15 <style>
16 </style>

views/My.vue

 1 <template>
 2   <div>
 3     <p>我的音乐</p>
 4     <p>我的音乐</p>
 5     <p>我的音乐</p>
 6     <p>我的音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyMusic'
13 }
14 </script>
15 <style>
16 </style>

3、根组件App.vue,使用route-link替换调a标签,使用router-link标签,相较于上面使用a标签,多了两个类名。router-link-active 和 router-link-exact-active

 

 1 <template>
 2   <div>
 3     <div class="footer_wrap">
 4       <router-link to="/find">发现音乐</router-link>
 5       <router-link to="/my">我的音乐</router-link>
 6       <router-link to="/friend">朋友</router-link>
 7     </div>
 8     <div class="top">
 9       <!-- 路由出口 → 匹配的组件所展示的位置 -->
10       <router-view></router-view>
11     </div>
12   </div>
13 </template>
14 
15 <script>
16 export default {};
17 </script>
18 
19 <style>
20 body {
21   margin: 0;
22   padding: 0;
23 }
24 .footer_wrap {
25   position: relative;
26   left: 0;
27   top: 0;
28   display: flex;
29   width: 100%;
30   text-align: center;
31   background-color: #333;
32   color: #ccc;
33 }
34 .footer_wrap a {
35   flex: 1;
36   text-decoration: none;
37   padding: 20px 0;
38   line-height: 20px;
39   background-color: #333;
40   color: #ccc;
41   border: 1px solid black;
42 }
43 .footer_wrap a.router-link-active {   // 模糊匹配,地址栏/find 或者/find/one  都会匹配
44   background-color: purple;
45 }
46 .footer_wrap a:hover {
47   background-color: #555;
48 }
49 </style>

4、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

 

声明式导航-导航高亮 两个类名

  

 1 // router-link-active 模糊匹配(更多)
 2 // to="/find"  =>  地址栏: /find  或  /find/one  或 /find/two
 3 .footer_wrap a.router-link-active {
 4   background-color: purple;
 5 }
 6 
 7 // router-link-exact-active 精确匹配
 8 // to="/find"  =>  地址栏只能是 /find  才会高亮
 9 .footer_wrap a.router-link-active {
10   background-color: purple;
11 }

声明式导航-自定义高亮类名

  

 1、router目录下index.js

 1 import Find from '@/views/Find'
 2 import My from '@/views/My'
 3 import Friend from '@/views/Friend'
 4 
 5 import Vue from 'vue'
 6 import VueRouter from 'vue-router'
 7 Vue.use(VueRouter) // VueRouter插件初始化
 8 
 9 // 创建了一个路由对象
10 const router = new VueRouter({
11   // routes 路由规则们
12   // route  一条路由规则 { path: 路径, component: 组件 }
13   routes: [
14     { path: '/find', component: Find },
15     { path: '/my', component: My },
16     { path: '/friend', component: Friend },
17   ],
18   // link自定义高亮类名
19   linkActiveClass: 'active', // 配置模糊匹配的类名
20   linkExactActiveClass: 'exact-active' // 配置精确匹配的类名
21 })
22 
23 export default router

2、views视图目录下

Find.vue

 1 <template>
 2   <div>
 3     <p>发现音乐</p>
 4     <p>发现音乐</p>
 5     <p>发现音乐</p>
 6     <p>发现音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'FindMusic'
13 }
14 </script>
15 <style>
16 </style>

Friend.vue

 1 <template>
 2   <div>
 3     <p>我的朋友</p>
 4     <p>我的朋友</p>
 5     <p>我的朋友</p>
 6     <p>我的朋友</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyFriend'
13 }
14 </script>
15 <style>
16 </style>

My.vue

 1 <template>
 2   <div>
 3     <p>我的音乐</p>
 4     <p>我的音乐</p>
 5     <p>我的音乐</p>
 6     <p>我的音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyMusic'
13 }
14 </script>
15 <style>
16 </style>

3、根组件App.vue

 1 <template>
 2   <div>
 3     <div class="footer_wrap">
 4       <router-link to="/find">发现音乐</router-link>
 5       <router-link to="/my">我的音乐</router-link>
 6       <router-link to="/friend">朋友</router-link>
 7     </div>
 8     <div class="top">
 9       <!-- 路由出口 → 匹配的组件所展示的位置 -->
10       <router-view></router-view>
11     </div>
12   </div>
13 </template>
14 
15 <script>
16 export default {};
17 </script>
18 
19 <style>
20 body {
21   margin: 0;
22   padding: 0;
23 }
24 .footer_wrap {
25   position: relative;
26   left: 0;
27   top: 0;
28   display: flex;
29   width: 100%;
30   text-align: center;
31   background-color: #333;
32   color: #ccc;
33 }
34 .footer_wrap a {
35   flex: 1;
36   text-decoration: none;
37   padding: 20px 0;
38   line-height: 20px;
39   background-color: #333;
40   color: #ccc;
41   border: 1px solid black;
42 }
43 .footer_wrap a.active {  // 使用自定义的高亮类名
44   background-color: purple;
45 }
46 .footer_wrap a:hover {
47   background-color: #555;
48 }
49 </style>

4、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

 

声明式导航-路由嵌套

1、reouter目录下index.js

 1 import Find from "@/views/Find";
 2 import My from "@/views/My";
 3 import Friend from "@/views/Friend";
 4 
 5 import Recommend from "@/views/Recommend";
 6 import ArtList from "@/views/ArtList";
 7 import TopList from "@/views/TopList";
 8 
 9 import Vue from "vue";
10 import VueRouter from "vue-router";
11 Vue.use(VueRouter); // VueRouter插件初始化
12 
13 // 创建了一个路由对象
14 const router = new VueRouter({
15   routes: [
16     {
17       path: "/find",
18       component: Find,
19       // 嵌套的子路由, 省略前缀/, 会自动拼接父路由地址/find/recommend
20       children: [
21         { path: "recommend", component: Recommend },
22         { path: "artlist", component: ArtList },
23         { path: "toplist", component: TopList },
24       ],
25     },
26     { path: "/my", component: My },
27     { path: "/friend", component: Friend },
28   ],
29 });
30 
31 export default router;

2、视图目录下

views/Find.vue

 1 <template>
 2   <div class="box">
 3     <!-- 发现音乐 -->
 4     <div class="link">
 5       <router-link to="/find/recommend">推荐</router-link>
 6       <router-link to="/find/toplist">排行榜</router-link>
 7       <router-link to="/find/artlist">歌手</router-link>
 8     </div>
 9     <div class="content">
10       <router-view></router-view>
11     </div>
12   </div>
13 </template>
14 
15 <script>
16 export default {
17   name: 'FindMusic'
18 }
19 </script>
20 
21 <style lang="less" scoped>
22 .box {
23   padding: 15px;
24 }
25 
26 .link {
27   a {
28     padding-right: 10px;
29     text-decoration: none;
30     color: #424242;
31   }
32 }
33 
34 .content {
35   padding: 10px;
36 }
37 </style>

views/Friend.vue

 1 <template>
 2   <div>
 3     <p>我的朋友</p>
 4     <p>我的朋友</p>
 5     <p>我的朋友</p>
 6     <p>我的朋友</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyFriend'
13 }
14 </script>
15 <style>
16 </style>

views/My.vue

 1 <template>
 2   <div>
 3     <p>我的音乐</p>
 4     <p>我的音乐</p>
 5     <p>我的音乐</p>
 6     <p>我的音乐</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'MyMusic'
13 }
14 </script>
15 <style>
16 </style>

  Find下面的子路由

views/ArtList.vue

 1 <template>
 2   <div>
 3     <h3>歌手</h3>
 4   </div>
 5 </template>
 6 
 7 <script>
 8 export default {
 9   name: 'ArtList'
10 }
11 </script>
12 
13 <style lang="less" scoped>
14 </style>

views/Recommend.vue

 1 <template>
 2   <div>
 3     <h2>推荐</h2>
 4   </div>
 5 </template>
 6 
 7 <script>
 8 export default {
 9   name: 'recommendPage'
10 }
11 </script>
12 
13 <style lang="less" scoped></style>

views/TopList.vue

 1 <template>
 2   <div>
 3     <h2>排行榜</h2>
 4   </div>
 5 </template>
 6 
 7 <script>
 8 export default {
 9   name: 'TopList'
10 }
11 </script>
12 
13 <style lang="less" scoped>
14 </style>

3、根组件App.vue

 1 <template>
 2   <div>
 3     <div class="footer_wrap">
 4       <router-link to="/find">发现音乐</router-link>
 5       <router-link to="/my">我的音乐</router-link>
 6       <router-link to="/friend">朋友</router-link>
 7     </div>
 8     <div class="top">
 9       <!-- 路由出口 → 匹配的组件所展示的位置 -->
10       <router-view></router-view>
11     </div>
12   </div>
13 </template>
14 
15 <script>
16 export default {};
17 </script>
18 
19 <style>
20 body {
21   margin: 0;
22   padding: 0;
23 }
24 .footer_wrap {
25   position: relative;
26   left: 0;
27   top: 0;
28   display: flex;
29   width: 100%;
30   text-align: center;
31   background-color: #333;
32   color: #ccc;
33 }
34 .footer_wrap a {
35   flex: 1;
36   text-decoration: none;
37   padding: 20px 0;
38   line-height: 20px;
39   background-color: #333;
40   color: #ccc;
41   border: 1px solid black;
42 }
43 .footer_wrap a.router-link-active {
44   background-color: purple;
45 }
46 .footer_wrap a:hover {
47   background-color: #555;
48 }
49 </style>

4、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

声明式导航-路由传参

  目标:在跳转路由时, 进行传值

  

1、router/index.js

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import Vue from 'vue'
 4 import VueRouter from 'vue-router'
 5 Vue.use(VueRouter) // VueRouter插件初始化
 6 
 7 // 创建了一个路由对象
 8 const router = new VueRouter({
 9   routes: [
10     { path: '/home', component: Home },
11     { path: '/search', component: Search }
12   ]
13 })
14 
15 export default router

2、视图页面

views/Home.vue

 1 <template>
 2   <div class="home">
 3     <div class="logo-box"></div>
 4     <div class="search-box">
 5       <input type="text">
 6       <button>搜索一下</button>
 7     </div>
 8     <div class="hot-link">
 9       热门搜索:
10       <!-- 通过路由跳转的时候, 将查询参数传递到子路由 -->
11       <router-link to="/search?key=黑马程序员">黑马程序员</router-link>
12       <router-link to="/search?key=前端培训">前端培训</router-link>
13       <router-link to="/search?key=如何成为前端大牛">如何成为前端大牛</router-link>
14     </div>
15   </div>
16 </template>
17 
18 <script>
19 export default {
20   name: 'FindMusic'
21 }
22 </script>
23 
24 <style>
25 .logo-box {
26   height: 150px;
27   background: url('@/assets/logo.jpeg') no-repeat center;
28 }
29 .search-box {
30   display: flex;
31   justify-content: center;
32 }
33 .search-box input {
34   width: 400px;
35   height: 30px;
36   line-height: 30px;
37   border: 2px solid #c4c7ce;
38   border-radius: 4px 0 0 4px;
39   outline: none;
40 }
41 .search-box input:focus {
42   border: 2px solid #ad2a26;
43 }
44 .search-box button {
45   width: 100px;
46   height: 36px;
47   border: none;
48   background-color: #ad2a26;
49   color: #fff;
50   position: relative;
51   left: -2px;
52   border-radius: 0 4px 4px 0;
53 }
54 .hot-link {
55   width: 508px;
56   height: 60px;
57   line-height: 60px;
58   margin: 0 auto;
59 }
60 .hot-link a {
61   margin: 0 5px;
62 }
63 </style>

views/Search.vue

 1 <template>
 2   <div class="search">
 3     <p>搜索关键字: {{ $route.query.key }} </p>
 4     <p>搜索结果: </p>
 5     <ul>
 6       <li>.............</li>
 7       <li>.............</li>
 8       <li>.............</li>
 9       <li>.............</li>
10     </ul>
11   </div>
12 </template>
13 
14 <script>
15 export default {
16   name: 'MyFriend',
17   created () {
18     // 在created中,获取路由参数
19     // this.$route.query.参数名 获取
20     console.log(this.$route.query.key);
21   }
22 }
23 </script>
24 
25 <style>
26 .search {
27   width: 400px;
28   height: 240px;
29   padding: 0 20px;
30   margin: 0 auto;
31   border: 2px solid #c4c7ce;
32   border-radius: 5px;
33 }
34 </style>

3、根组件App.vue

 1 <template>
 2   <div id="app">
 3     <div class="link">
 4       <router-link to="/home">首页</router-link>
 5       <router-link to="/search">搜索页</router-link>
 6     </div>
 7 
 8     <router-view></router-view>
 9   </div>
10 </template>
11 
12 <script>
13 export default {};
14 </script>
15 
16 <style scoped>
17 .link {
18   height: 50px;
19   line-height: 50px;
20   background-color: #495150;
21   display: flex;
22   margin: -8px -8px 0 -8px;
23   margin-bottom: 50px;
24 }
25 .link a {
26   display: block;
27   text-decoration: none;
28   background-color: #ad2a26;
29   width: 100px;
30   text-align: center;
31   margin-right: 5px;
32   color: #fff;
33   border-radius: 5px;
34 }
35 </style>

4、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

  

 1、router/index.js

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import Vue from 'vue'
 4 import VueRouter from 'vue-router'
 5 Vue.use(VueRouter) // VueRouter插件初始化
 6 
 7 // 创建了一个路由对象
 8 const router = new VueRouter({
 9   routes: [
10     { path: '/home', component: Home },
11     // path: '/search/:参数1/:参数2'
12     { path: '/search/:words', component: Search }
13   ]
14 })
15 
16 export default router

2、视图页面

views/Home.vue

 1 <template>
 2   <div class="home">
 3     <div class="logo-box"></div>
 4     <div class="search-box">
 5       <input type="text">
 6       <button>搜索一下</button>
 7     </div>
 8     <div class="hot-link">
 9       热门搜索:
10       <!-- 通过动态路由传参 -->
11       <router-link to="/search/黑马程序员">黑马程序员</router-link>
12       <router-link to="/search/前端培训">前端培训</router-link>
13       <router-link to="/search/如何成为前端大牛">如何成为前端大牛</router-link>
14     </div>
15   </div>
16 </template>
17 
18 <script>
19 export default {
20   name: 'FindMusic'
21 }
22 </script>
23 
24 <style>
25 .logo-box {
26   height: 150px;
27   background: url('@/assets/logo.jpeg') no-repeat center;
28 }
29 .search-box {
30   display: flex;
31   justify-content: center;
32 }
33 .search-box input {
34   width: 400px;
35   height: 30px;
36   line-height: 30px;
37   border: 2px solid #c4c7ce;
38   border-radius: 4px 0 0 4px;
39   outline: none;
40 }
41 .search-box input:focus {
42   border: 2px solid #ad2a26;
43 }
44 .search-box button {
45   width: 100px;
46   height: 36px;
47   border: none;
48   background-color: #ad2a26;
49   color: #fff;
50   position: relative;
51   left: -2px;
52   border-radius: 0 4px 4px 0;
53 }
54 .hot-link {
55   width: 508px;
56   height: 60px;
57   line-height: 60px;
58   margin: 0 auto;
59 }
60 .hot-link a {
61   margin: 0 5px;
62 }
63 </style>

views/Search.vue

 1 <template>
 2   <div class="search">
 3     <p>搜索关键字: {{ $route.params.words }} </p>
 4     <p>搜索结果: </p>
 5     <ul>
 6       <li>.............</li>
 7       <li>.............</li>
 8       <li>.............</li>
 9       <li>.............</li>
10     </ul>
11   </div>
12 </template>
13 
14 <script>
15 export default {
16   name: 'MyFriend',
17   created () {
18     // 在created中,获取路由参数
19     // this.$route.query.参数名 获取查询参数
20     // this.$route.params.参数名 获取动态路由参数
21     console.log(this.$route.params.words);
22   }
23 }
24 </script>
25 
26 <style>
27 .search {
28   width: 400px;
29   height: 240px;
30   padding: 0 20px;
31   margin: 0 auto;
32   border: 2px solid #c4c7ce;
33   border-radius: 5px;
34 }
35 </style>

3、根组件App.vue

 1 <template>
 2   <div id="app">
 3     <div class="link">
 4       <router-link to="/home">首页</router-link>
 5       <router-link to="/search">搜索页</router-link>
 6     </div>
 7     <router-view></router-view>
 8   </div>
 9 </template>
10 
11 <script>
12 export default {};
13 </script>
14 
15 <style scoped>
16 .link {
17   height: 50px;
18   line-height: 50px;
19   background-color: #495150;
20   display: flex;
21   margin: -8px -8px 0 -8px;
22   margin-bottom: 50px;
23 }
24 .link a {
25   display: block;
26   text-decoration: none;
27   background-color: #ad2a26;
28   width: 100px;
29   text-align: center;
30   margin-right: 5px;
31   color: #fff;
32   border-radius: 5px;
33 }
34 </style>

4、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

  

 


 

 动态路由参数可选符

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import Vue from 'vue'
 4 import VueRouter from 'vue-router'
 5 Vue.use(VueRouter) // VueRouter插件初始化
 6 
 7 // 创建了一个路由对象
 8 const router = new VueRouter({
 9   routes: [
10     { path: '/home', component: Home },
11     // path: '/search/:words?' ->  ? 表示参数words可以没有, 此时路由匹配: /search 和 带参数的  /search/:words,  :后面的words为自定义变量,用于子路由获取传参时使用, this.$route.params.words ,这个words与:后面的单词保持一致
12     { path: '/search/:words?', component: Search }
13   ]
14 })
15 
16 export default router

路由重定向

  

 router/index.js   路由配置的js文件

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import Vue from 'vue'
 4 import VueRouter from 'vue-router'
 5 Vue.use(VueRouter) // VueRouter插件初始化
 6 
 7 // 创建了一个路由对象
 8 const router = new VueRouter({
 9   routes: [
10     // 路由重定向,当我们访问项目根目录的时候, 默认重定向到/home视图
11     { path: '/', redirect: '/home' },
12     { path: '/home', component: Home },
13     { path: '/search/:words?', component: Search }
14   ]
15 })
16 
17 export default router

路由404

  

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import NotFound from '@/views/NotFound'
 4 import Vue from 'vue'
 5 import VueRouter from 'vue-router'
 6 Vue.use(VueRouter) // VueRouter插件初始化
 7 
 8 // 创建了一个路由对象
 9 const router = new VueRouter({
10   routes: [
11     // 路由重定向, 当我们访问项目根目录的时候, 默认重定向到/home视图
12     { path: '/', redirect: '/home' },
13     { path: '/home', component: Home },
14     { path: '/search/:words?', component: Search },
15     // 通配符, 当上面的所有路由规则都没有匹配到时, 走这条兜底规则, 展示默认的NotFound页面
16     { path: '*', component: NotFound }
17   ]
18 })
19 
20 export default router

路由模式设置

  

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import NotFound from '@/views/NotFound'
 4 import Vue from 'vue'
 5 import VueRouter from 'vue-router'
 6 Vue.use(VueRouter) // VueRouter插件初始化
 7 
 8 
 9 const router = new VueRouter({
10   // 注意:一旦采用了 history 模式,地址栏就没有 #,需要后台配置访问规则
11   mode: 'history',
12   routes: [
13     { path: '/', redirect: '/home' },
14     { path: '/home', component: Home },
15     { name: 'search', path: '/search/:words?', component: Search },
16     { path: '*', component: NotFound }
17   ]
18 })
19 export default router

编程式导航 -用JS代码来进行跳转

① path 路径跳转

 1 // 通过路由的path跳转
 2 // 1、不带参数
 3 this.$router.push('路由路径')
 4 // 2、带query传参
 5 this.$router.push('/路径?参数名1=参数值1&参数2=参数值2')
 6 // 3、带query传参完整写法
 7 this.$router.push({
 8     path: '路由路径',
 9     query: {
10         参数名1: '参数值1',
11         参数名2: '参数值2'
12     }
13 })
14 // 接受参数的方式依然是:$route.query.参数名
15 
16 // 4、动态路由传参
17 this.$router.push('/路径/参数值1/参数2')
18 // 5、动态路由传参完整写法
19 this.$router.push({
20     path: '/路径/参数值1/参数2'
21 })
22 // 接受参数的方式依然是:$route.params.参数值

② name 命名路由跳转

 1 // 前提: 路由规则配置新增name属性
 2 { name: '路由名', path: '/path/xxx', component: XXX }
 3 
 4 // 通过name进行跳转
 5 this.$router.push({
 6     name: '路由名'
 7 })
 8 
 9 // query传参
10 this.$router.push({
11     name: '路由名字',
12     query: {
13         参数名1: '参数值1',
14         参数名2: '参数值2'
15     }
16 })
17 // 动态路由传参 (需要配动态路由)
18 this.$router.push({
19     name: '路由名字',
20     params: {
21         参数名: '参数值',
22     }
23 })

 

编程式导航示例

1、router/index.js

 1 import Home from '@/views/Home'
 2 import Search from '@/views/Search'
 3 import NotFound from '@/views/NotFound'
 4 import Vue from 'vue'
 5 import VueRouter from 'vue-router'
 6 Vue.use(VueRouter) // VueRouter插件初始化
 7 
 8 // 创建了一个路由对象
 9 const router = new VueRouter({
10   // 注意:一旦采用了 history 模式,地址栏就没有 #,需要后台配置访问规则
11   mode: 'history',
12   routes: [
13     { path: '/', redirect: '/home' },
14     { path: '/home', component: Home },
15     { name: 'search', path: '/search/:words?', component: Search },
16     { path: '*', component: NotFound }
17   ]
18 })
19 
20 export default router

2、视图目录下

views/Home.vue

  1 <template>
  2   <div class="home">
  3     <div class="logo-box"></div>
  4     <div class="search-box">
  5       <input v-model="inpValue" type="text">
  6       <button @click="goSearch">搜索一下</button>
  7     </div>
  8     <div class="hot-link">
  9       热门搜索:
 10       <router-link to="/search/黑马程序员">黑马程序员</router-link>
 11       <router-link to="/search/前端培训">前端培训</router-link>
 12       <router-link to="/search/如何成为前端大牛">如何成为前端大牛</router-link>
 13     </div>
 14   </div>
 15 </template>
 16 
 17 <script>
 18 export default {
 19   name: 'FindMusic',
 20   data () {
 21     return {
 22       inpValue: ''
 23     }
 24   },
 25   methods: {
 26     goSearch () {
 27       // 1. 通过路径的方式跳转
 28       // (1) this.$router.push('路由路径') [简写]
 29       //     this.$router.push('路由路径?参数名=参数值')
 30       // this.$router.push('/search')
 31       // this.$router.push(`/search?key=${this.inpValue}`)
 32       // this.$router.push(`/search/${this.inpValue}`)
 33 
 34       // (2) this.$router.push({     [完整写法] 更适合传参
 35       //         path: '路由路径'
 36       //         query: {
 37       //            参数名: 参数值,
 38       //            参数名: 参数值
 39       //         }
 40       //     })
 41       // this.$router.push({
 42       //   path: '/search',
 43       //   query: {
 44       //     key: this.inpValue
 45       //   }
 46       // })
 47       // this.$router.push({
 48       //   path: `/search/${this.inpValue}`
 49       // })
 50 
 51 
 52 
 53       // 2. 通过命名路由的方式跳转 (需要给路由起名字) 适合长路径
 54       //    this.$router.push({
 55       //        name: '路由名'
 56       //        query: { 参数名: 参数值 },
 57       //        params: { 参数名: 参数值 }
 58       //    })
 59       this.$router.push({
 60         name: 'search',
 61         // query: {
 62         //   key: this.inpValue
 63         // }
 64         params: {
 65           words: this.inpValue
 66         }
 67       })
 68     }
 69   }
 70 }
 71 </script>
 72 
 73 <style>
 74 .logo-box {
 75   height: 150px;
 76   background: url('@/assets/logo.jpeg') no-repeat center;
 77 }
 78 .search-box {
 79   display: flex;
 80   justify-content: center;
 81 }
 82 .search-box input {
 83   width: 400px;
 84   height: 30px;
 85   line-height: 30px;
 86   border: 2px solid #c4c7ce;
 87   border-radius: 4px 0 0 4px;
 88   outline: none;
 89 }
 90 .search-box input:focus {
 91   border: 2px solid #ad2a26;
 92 }
 93 .search-box button {
 94   width: 100px;
 95   height: 36px;
 96   border: none;
 97   background-color: #ad2a26;
 98   color: #fff;
 99   position: relative;
100   left: -2px;
101   border-radius: 0 4px 4px 0;
102 }
103 .hot-link {
104   width: 508px;
105   height: 60px;
106   line-height: 60px;
107   margin: 0 auto;
108 }
109 .hot-link a {
110   margin: 0 5px;
111 }
112 </style>

views/Search.vue

 1 <template>
 2   <div class="search">
 3     <!-- 获取路由参数 -->
 4     <p>搜索关键字: {{ $route.params.words }} </p>
 5     <p>搜索结果: </p>
 6     <ul>
 7       <li>.............</li>
 8       <li>.............</li>
 9       <li>.............</li>
10       <li>.............</li>
11     </ul>
12   </div>
13 </template>
14 
15 <script>
16 export default {
17   name: 'MyFriend',
18   created () {
19     // 在created中,获取路由参数
20     // this.$route.query.参数名 获取查询参数
21     // this.$route.params.参数名 获取动态路由参数
22     // console.log(this.$route.params.words);
23   }
24 }
25 </script>
26 <style>
27 .search {
28   width: 400px;
29   height: 240px;
30   padding: 0 20px;
31   margin: 0 auto;
32   border: 2px solid #c4c7ce;
33   border-radius: 5px;
34 }
35 </style>

3、根组件App.vue

 1 <template>
 2   <div id="app">
 3     <div class="link">
 4       <router-link to="/home">首页</router-link>
 5       <router-link to="/search">搜索页</router-link>
 6     </div>
 7     <router-view></router-view>
 8   </div>
 9 </template>
10 
11 <script>
12 export default {};
13 </script>
14 
15 <style scoped>
16 .link {
17   height: 50px;
18   line-height: 50px;
19   background-color: #495150;
20   display: flex;
21   margin: -8px -8px 0 -8px;
22   margin-bottom: 50px;
23 }
24 .link a {
25   display: block;
26   text-decoration: none;
27   background-color: #ad2a26;
28   width: 100px;
29   text-align: center;
30   margin-right: 5px;
31   color: #fff;
32   border-radius: 5px;
33 }
34 </style>

4、main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import router from './router/index'
 4 
 5 Vue.config.productionTip = false
 6 
 7 new Vue({
 8   render: h => h(App),
 9   router
10 }).$mount('#app')

 路由守卫

 1 import Vue from 'vue'
 2 import VueRouter from 'vue-router'
 3 import { getToken } from '@/utils/storage'
 4 
 5 // 一级路由页面的导入
 6 const Login = () => import('@/views/Login')
 7 const Register = () => import('@/views/Register')
 8 const Layout = () => import('@/views/Layout')
 9 const Detail = () => import('@/views/Detail')
10 
11 // 二级路由页面的导入
12 const Article = () => import('@/views/Article')
13 const Collect = () => import('@/views/Collect')
14 const Like = () => import('@/views/Like')
15 const User = () => import('@/views/User')
16 
17 Vue.use(VueRouter)
18 
19 const router = new VueRouter({
20   routes: [
21     { path: '/login', component: Login },
22     { path: '/register', component: Register },
23     { path: '/article/:id', component: Detail },
24     {
25       path: '/',
26       component: Layout,
27       redirect: '/article',
28       children: [
29         { path: '/article', component: Article },
30         { path: '/like', component: Like },
31         { path: '/collect', component: Collect },
32         { path: '/user', component: User }
33       ]
34     }
35   ]
36 })
37 
38 // 白名单(就是一个数组,数组收录所有无需登录即可访问的页面)
39 const whiteList = ['/login', '/register']
40 
41 // 路由前置守卫
42 // 1. to 往哪去
43 // 2. from 从哪来
44 // 3. next 是否放行 next() 放行 next(路径) 拦截到某个页面
45 router.beforeEach((to, from, next) => {
46   const token = getToken()
47   if (token) {
48     // 如果有token,直接放行
49     next()
50   } else {
51     // 没有token的人,看看要去哪
52     // 判断访问的路径 to.path, 是否在白名单中
53     if (whiteList.includes(to.path)) {
54       next()
55     } else {
56       next('/login')
57     }
58   }
59 })
60 
61 export default router

 

组件缓存 keep-alive

  

 

  

 

  

  

 

  

 

posted @ 2024-04-08 10:36  为你编程  阅读(46)  评论(0编辑  收藏  举报