浅谈路由

115 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

SPA与前端路由

SPA指的是一个web网站只有唯一的一个HTML页面,所有组件的展示与切换都在唯一的一个页面完成,此时,不同组件之间的切换需要通过前端路由来实现

总结:在SPA的项目中,不同功能之间的切换,要依赖于前端路由来完成

前端路由

路由就是对应关系(地址和组件的对应关系,不同的地址展示不同的组件)

通俗易懂:hash地址(地址栏里#开头的地址)和组件之间的对应关系

前端路由的工作方式;

  • 用户点击了页面上的路由链接(本质就是a链接)
  • 导致了URL地址栏中的hash值发生了变化
  • 前端路由监听到了hash地址的变化
  • 前端路由把当前hash地址对应的组件渲染到浏览器中

总结:用户点击链接导致hash地址变化,hash地址的变化被前端路由监听到,然后前端路由匹配到对应组件并展示出来

image.png

后端路由:请求方式和请求地址与function处理函数之间的对应关系

前端路由:hash地址和组件之间的对应关系

vue-router的基本使用

是vue项目中路由包,react项目中不能用

步骤:

  • 下载vue-router模块到当前项目
npm  i  vue-router
  • 在main.js中引入vue-router
import VueRouter  from  'vue-router'
  • 使用Vue.sue()方法给vue安装插件-
Vue.sue(VueRouter)  //内部自动帮我们注册注册全局RouterLink(链接)和RouterView(占位符)组件
  • 创建路由规则数组-路径和组件名对应关系
const routes=[
  {path:'/find',component:Find},
  {path:'/my',component:My},
  {path:'/part',component:Part},
]
  • 用规则生成路由对象
const router=new VueRouter({
    routes:routes  //可简写
})
  • 把路由对象注入到new Vue 实例中
new Vue({
  render: h => h(App),
   router //注入到vue实例中
}).$mount('#app')
​
  • 用router-view作为挂载点,切换不同的路由页面
 <router-view></router-view>  //占位符,将来组件切换显示的地方

1、导入组件和创建路由规则都在mani.js里

2、挂在点写在要显示地方的组件里

声明式导航

在vue中使用来声明路由链接

并使用来声明路由占位符

注意:这两个组件是下载的路由包帮我们提供的组件

<template>
    <h1> APP组件</h1>
    #声明路由链接  
    <router-link  to="/home">首页</router-link> // 用to属性替代a链接的href属性
    <router-link  to="/move">电影</router-link>
    <router-link  to="/about">关于</router-link>
    
    #声明路由占位符————匹配到什么组件,就在这个位置渲染什么组件
    <router-view></router-view>
</template>

1、声明hash地址使用to来声明,不用#开头,vue-router渲染时自动生成#(替代a标签)

2、router-link实质上最终会渲染成a链接 to属性等价于提供 href属性(to无需#)

3、router-link提供了声明式导航高亮的功能(自带激活时的类名,可以做高亮)

编程式导航

通过调用API实现导航的方式,叫做编程式导航

与之对应,通过点击链接实现导航的方式,叫做声明式导航

#可用在点击按钮 事件里 实现跳转    
this.$router.push('hash地址') //跳转到指定hash地址,从而展示对应的组件
this.$router.push({
    path:'路由路径', 
    name:'路由名',//首先要在路由规则里添加name属性  
    //path和name都可以进行传参,二选一即可
    query:{
        参数名:值
    },
    params:{
        参数名:值
    }
})
#因为传参path会忽略params,所以可以规定以后使用编程式跳转时使用name跳转,以免bug 
#可用在点击按钮 事件里 实现前进后退
this.$router.go(数值 n)//实现导航历史的前进、后退

使用编程式跳转,传参不需要在规则里传参数

使用声明式跳转,传参有时需要在规则里传参数名

路由传参

在跳转路由时, 可以给路由对应的组件内传值

#在router-link上的to属性传值, 语法格式如下
<router-link> to="/home?参数名=值">首页</router-link>    //URL?a=1&b=2
<router-link> to="/home/值">首页</router-link>  // URL/:id (需在路由规则里配置/path/:参数名)
#对应页面组件接收传递过来的值
 $route.query.参数名  接收字符串格式的参数(查询参数)
 $route.params.参数名  接收动态路由格式的参数(路由参数)

重定向

用户在访问地址A的时候,强制用户跳转到地址C,从而展示特定的组件页面

#在路由规则最前面添加,页面一打开就显示重定向的组件
//其中path表示 需要被重定向指定的原地址,redirect表示将要被重定向的新地址 
{path:'/',redirect:'/home'} //网页打开url默认hash值是/路径(页面一打开就访问home)

路由模式切换

修改路由在地址栏的模式

#hash路由例如: http://localhost:8080/#/home
const router=new VueRouter({
    routes,
    mode:'hash'
})
#history路由例如: http://localhost:8080/home (以后上线需要服务器端支持, 否则找的是文件夹)
const router=new VueRouter({
    routes,
    mode:'history'
})

访问路径不存在

找不到路径给个提示页面

 #路由规则最后, path匹配*(任意路径) – 前面不匹配就命中最后这个
//先导入显示页面不存在的组件
 improt NotFound from "@/views/NotFound"
//在数组规则最后一个里定义这个规则
{path:'*',component:NotFound},

在数组最后一个位置, 插入匹配*的规则, 展示404页面

嵌套路由

通过路由实现组件的嵌套展示,叫做嵌套路由

image.png

通过children属性声明子路由规则,子路由规则里
 routers:[
     {//父级路由规则
         path:'/about',
         component:about,
         children:[ //通过children 属性嵌套子级路由规则
                  {path:'tab1',component:Tab1},//访问/about/tab1时,展示Tab1组件
                  {path:'tab2',component:Tab2},//访问/about/tab2时,展示Tab2组件
                
         ]
     }
    ]
# 在子路由path里不要/开头,不加/会自动和about连接,/表示目录

动态路由匹配

一个路由规则能够匹配到多个路由的链接

动态路由:把hash地址中可变的部分定义为参数,从而提高路由规则的复用性

在vue-router中使用:来定义路由的参数项

//路由中的动态参数以:进行声明,冒号后面的是动态参数的名称
{path:'/movie/:id',component:Movie}
​
//将以下3个路由规则,合并成了一个,提高了路由规则的复用性
{path:'/move/1',component:Movie}
{path:'/move/2',component:Movie}
{path:'/move/3',component:Movie}

导航守卫

导航守卫用来控制路由的访问权限

image.png

#声明导航守卫:全局导航守卫会拦截每个路由规则,从而对每个路由进行访问权限的控制
1、调用路由实例对象的beforeEach函数,声明全局前置守卫
2fn必须是一个函数,每次拦截到路由请求,都会调用fn进行处理
3、因此fn叫做守卫方法
router.beforeEach(fn)//路由跳转之前执行这个函数,来决定要不要跳转

守卫方法的三个形参

router.beforeEach((to,from,next)=>{
    //to目标路由对象
    //from 当前导航正要离开的路由对象
    //next 是一个函数,表示放行
})

在守卫方法中如果不声明next形参,则默认允许访问每一个路由

在守卫方法中如果声明了next形参,则必须调用next()函数,否则不允许用户访问任何一个路由

next三种调用方式

直接放行:next()
强制其停留在当前页面:nextfalse)
强制其跳转到登录页面:next'/login'

结合token控制后台主页的访问权限

image.png

要return

动态组件的使用

动态组件指的是动态切换的组件显示与隐藏:多个组件使用同一个挂载点,并动态切换

vue提供了一个内置的组件,专门用来实现动态组件的渲染

引入组件并且注册组件后,使用变量接受来承载要动态显示的组件
import user from '组件路径'  //1、导入组件
export default {
    components:{
        user   //2、注册组件
    },
    data(){
        retuen{
            user:'user'  //3、使用变量接收要动态显示的组件
        }
    }
}
​
​
#在要动态显示组件的地方设置挂载点<component>,使用is属性来设置要显示哪个组件
# is="接收组件的变量名"
<div>
 <component :is="user"></component>    //is指定当前占位符显示哪个组件  
</div>
​
注意:is属性的值一定是变量,只有是变量才能动态切换

设置动态组件被缓存

目的:使用动态组件时,每一次发生组件切换时,被隐藏的的组件会销毁展示出来的组件会被重新创建,重新初始化

需求:将隐藏时的组件不被销毁(使用keep-alive 保持状态)

原理:使用 标签可以将隐藏的组件缓存起来而已,不必销毁

拓展: 标签的include属性可设置哪些标签被缓存

exclude属性可设置哪些标签不被缓存

#需要设置name属性
export default {
    name:"xxx"  //设置name:组件名更改为被设置的名字,调试工具里也变成name的值
               //不设置name:组件名就是文件名,调试工具里显示的就是文件名
}
<keep-alive  include="组件name名1,组件name名2..."  > 
     <router-view ></router-view>  
 </keep-alive>
​

include属性可设置哪些标签被缓存

exclude属性可设置哪些标签不被缓存(不被设置的就会被缓存)

两者不能同时使用,二选一

监听组件切换的动态

需求:能够监听到组件被缓存时和激活是的状态

原理:vue提供了对应的声明周期函数

  • 当组件被缓存时,会自动出发组建的deactivated 生命周期函数
  • 当组件被激活时,会自动触发组件的activated生命周期函数