Vue---路由的使用

260 阅读7分钟

highlight: a11y-dark

Vue--路由的使用

路由的基本使用

在这里我做了一个极其简陋的页面,大家不要见怪哈。 主要分分为三个部分,头部的标题,左面的导航区,右面的内容展示区。 页面一.png 我们点击左面的导航,右面展示区就会显示对应的内容。现在我们来使用路由来完成这个功能。

第一步 安装vue-router

由于我的脚手架是2.0版本的,所以使用的路由就安装3.0的

npm i vue-router@3

第三步 引入并使用

在main.js中 引入并使用router插件

import Vue from 'vue'
import App from './App.vue'

//引入vue-router
import VueRouter from 'vue-router'

import store from './store/index'

//使用vue-router
Vue.use(VueRouter)
Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store,
  beforeCreate(){
    Vue.prototype.$bus=this//安装全局总线
  },
  router:Router
}).$mount('#app')

第三步配置路由信息

我们在src中新建一个文件夹名为router,里面创建一个index.js用来配置路由信息。

首先需要将vue-router引入,之后创建并暴露路由规则。路由的路径与跳转的组件写在routes中。他是一个数组,里面书写配置信息。

path:路径

component:此路径的组件

import VueRouter from 'vue-router'
import FirstDemo from '../pages/FirstDemo'
import SecondDemo from '../pages/SecondDemo'
import ThirdDemo from '../pages/ThirdDemo'

export default new VueRouter({
    routes:[
        {
            path:'/first',
            component:FirstDemo
        },
        {
            path:'/second',
            component:SecondDemo
        },
        {
            path:'/third',
            component:ThirdDemo
        },
    ]
})

在书写完路由信息后,将他引入在main.js中import Router from './router/index' 这样路由规则就配置好了。就可以使用了。

第四步 实现切换

我们知道在普通页面中,我们实现页面的跳转是靠a标签实现的,在这里我们要实现路由跳转用的是router-link这个标签,他与a类似,但又有区别。使用路由跳转可以做到页面无刷新更新页面内容。具体代码如下:

  <router-link to="/first" class="nav" active-class="active">第一个导航</router-link>
  <router-link to="/second" class="nav" active-class="active">第二个导航</router-link>
  <router-link to="/third" class="nav" active-class="active">第三个导航</router-link>

to表示要跳转的地址,这个我们在配置路由链接的时候就写好了,active-class可以设置被点击时的高亮显示。 接下来就是设置路由跳转后,页面在哪里显示了,使用<router-view></router-view>标签,完整代码如下:

<template>
<div>
  <router-link to="/first" class="nav" active-class="active">第一个导航</router-link>
  <router-link to="/second" class="nav" active-class="active">第二个导航</router-link>
  <router-link to="/third" class="nav" active-class="active">第三个导航</router-link>

  <div class="content">
    <router-view></router-view>
  </div>
</div>
  
</template>

页面效果 页面一.png 屏幕截图 2022-10-09 151122.png

屏幕截图 2022-10-09 151135.png

这就完成了路由的基本使用。

我们来总结一下:

  1. 下载
  2. 引入
  3. 在src下新建router文件夹,在里面新建index.js用来书写路由配置。
  4. 实现切换,使用router-link建立连接,使用router-view显示内容。

这就是路由的基本使用啦。

多级路由

多级路由在实践中也很常见,其实会了二级路由也就会了多级路由。在这里我就演示一个二级路由吧。

我们在第一个导航内容区域在设置两个导航项

屏幕截图 2022-10-09 160557.png

接下来配置路由信息,我们看到是在第一个导航内容中设置导航,所以得在第一个导航区的路由信息里配置子路由信息。使用children关键字。

{
            path:'/first',
            component:FirstDemo,
            children:[
                {
                    path:'news',
                    component:NewsDemo
                },
                {
                    path:'weather',
                    component:WeatherDemo
                }
            ]
        },

里面书写的内容和一级路由一模一样,但是要记得,path中不要再写‘/’。切记切记。 接下来写router-link与router-view

<template>
  <div>
    第一个导航的内容
    <ul>
      <router-link to='/first/news' active-class="active">新闻</router-link>
      <router-link to='/first/weather' active-class="active">天气</router-link>
    </ul>

    <div class="">
      <router-view></router-view>
    </div>
  </div>
</template>

这里有一个注意点,在to中一定要写完整的路由信息,否则会无法正常跳转。最后显示效果如下:

屏幕截图 2022-10-09 160557.png

屏幕截图 2022-10-09 162339.png

这就是二级路由,其实多级路由就是一直往里写Children.

我们来总结一下

  1. 配置路由信息,记得不要写'/'
  2. 写连接,写展示标签。(你们懂我意思哈)

携带query参数

现在有一个需求,点击一个消息,在他下下面显示出详细消息。

屏幕截图 2022-10-09 160557.png 我们在路由链接里将消息的详细内容,通过query参数传递给组件。

<template>
  <div>
    <ul>
      <router-link 
      :to='`/second/news?id=${p.id}&title=${p.title}`' //在这里携带query参数 ?后开始书写&符号拼接
      v-for="p in personList" :key="p.id"//用v-for遍历
      >
        {{p.title}}
      </router-link>
    </ul>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name:'SecondDemo',
  data(){
    return {
      personList:[
        {id:'001',title:'第一条消息'},
        {id:'002',title:'第二条消息'},
        {id:'003',title:'第三条消息'},
      ]
    }
  }
}
</script>

<style scoped>
a{
  text-decoration: none;
  color: black;
  margin: 10px;
}

</style>

这样我们就把query参数传递给了要展示的组件中。在组件中我们接收一下。

<template>
  <div>
    <ul>
        <li>{{$route.query.id}}</li>
        <li>{{$route.query.title}}</li>
    </ul>
  </div>
</template>

完成!

屏幕截图 2022-10-09 171510.png 但是吧,这种写法如果要携带的参数过于多,这种写法看上去就很难受了,所以还有另外一种写法。对象写法。这样写看起来就很好了。

<router-link 
       v-for="p in personList" :key="p.id"
      :to="{
        path:'/second/news',
        query:{
          id:p.id,
          title:p.title
        }
      } "
     
      >
        {{p.title}}
      </router-link>

路由命名

在前面我们写路径的时候发现,如果路径太长的话,很不方便观察,容易写错。这时就需要我们的路由命名了。我们给详细详情这个路径命名。

{
            path:'/second',
            component:SecondDemo,
            children:[
                {
                    name:'xiangq',
                    path:'news',
                    component:DetilDemo
                }
                
            ]
        },

这时候我们在传递参数时就可以写name,不用写path了。路由命名适用于路径特别长的时候,很方便。

<router-link 
       v-for="p in personList" :key="p.id"
      :to="{
        name:'xiangq',
        query:{
          id:p.id,
          title:p.title
        }
      }">

携带params参数

路由还可以携带params参数。我们做一个和携带query参数类似的案例。

屏幕截图 2022-10-09 171510.png 携带params参数的代码如下

<template>
  <div>
    第三个导航内容
    <ul>
      <router-link 
      :to='`/third/stunent/${s.id}/${s.sno}`'//携带params参数
      v-for='s in stuList' :key='s.id'>
        {{s.name}}
      </router-link>
    </ul>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name:'ThirdDemo',
  data(){
    return{
      stuList:[
        {id:'001',sno:'192100906',name:'张三'},
        {id:'002',sno:'192100908',name:'李四'}
        ]
    }
  }
}
</script>

携带params参数相对来说比较简单,直接在/ 后写参数即可,但是需要在路由配置里,声明一下参数。

{
    path:'/third',
    component:ThirdDemo,
    children:[
        {
            path:'stunent/:id/:sno',
            component:StudentDemo
        }
    ]
},

接收一下数据

<template>
  <ul>
    <li>{{$route.params.id}}</li>
    <li>{{$route.params.sno}}</li>
  </ul>
</template>

<script>
export default {
    name:'StudentDemo'
}
</script>

和携带query参数一样,携带params参数也有对象写法。

<router-link 
      :to="{//params参数的对象写法
        name:'stu',
        params:{
          id:s.id,
          sno:s.sno
        }
      }"
      v-for='s in stuList' :key='s.id'>
        {{s.name}}
      </router-link>

props配置

在前面,我们接收参数的时候,我们老写这样的代码。

<ul>
    <li>{{$route.params.id}}</li>
    <li>{{$route.params.sno}}</li>
  </ul>
<ul>
    <li>{{$route.query.id}}</li>
    <li>{{$route.query.title}}</li>
</ul>

这样其实不太符合vue的风格,要尽可能的简化{{}}里面的内容。这时我们就需要props配置了。props要写在路由配置里。peops配置有很多写法,在这里我就介绍函数式写法。

{
    path:'/third',
    component:ThirdDemo,
    children:[
        {
            name:'stu',
            path:'stunent/:id/:sno',
            component:StudentDemo,
            props($route){//props配置
                return{
                    id:$route.params.id,
                    sno:$route.params.sno
                }
            }
        }
    ]
},

配置完成之后需要在对应的组件接收,

<template>
  <ul>
    <li>{{id}}</li>
    <li>{{sno}}</li>
  </ul>
</template>

<script>
export default {
    name:'StudentDemo',
    props:['id','sno']
}
</script>

我们看到,使用props配置可以更方便的接收参数。

编程式路由导航

什么是编程式路由导航,我们先不管这个概念,在上面的路由中,我们实现路由跳转都是靠router-link这个标签,它类似于a标签,我们点击他,他才会跳转,如果有一个按钮,有一个图片想要实现路由跳转怎么办,这时就需要编程式路由导航了。

我们现在有两个按钮,如下,点击他实现路由跳转。

capture_20221010095646453.bmp 我们给这两个按钮绑定点击事件,然后调用路由器上两个api。

<template>
  <div>
    <button @click="eat">去吃饭</button>
    <button @click="sleep">去睡觉</button>
    
    <router-view></router-view>
  </div>
</template>

<script>
export default {
    name:'ForthDemo',
    methods:{
      eat(){
        this.$router.push({
          path:'/four/eat'
        })
      },
      sleep(){
        this.$router.push({
          path:'/four/sleep'
        })
      }
    },
}
</script>

<style>
button{
  margin: 10px;
}
</style>

在绑定的点击事件中,我调用了push这个方法,它里面传递配置对象,可以传递路径,query参数,params参数(当然不止这些),在这里为了简单我就不写了。效果如下

capture_20221010095646453.bmp

capture_20221010100543208.bmp 我们还可以在这个组件一挂载,调用一个定时器,2秒后实现路由跳转,这样就不用点击了,

mounted(){
      setTimeout(()=>{
        this.$router.push({
          path:'/four/eat'
        })
      },2000)
    }

还有一个api replace他与push的区别就是push会产生历史记录,而replace不会。使用方法完全一样。大家感兴趣可以试试。

缓存路由组件

我们首先要知道,我们点击一个路由组件,他会加载。当点出去时,他就会被销毁。当我们在组件中输入一些东西时,点到另外一个组件,再回来时输入的内容就不在了,怎么解决这个问题呢?我们可以使用缓存路由组件,在<router-view></router-view>外层使用keep-alive标签包裹。

<keep-alive include="EatDemo,SleepDemo">
  <router-view></router-view>
</keep-alive>

在include里写要缓存的组件名,这样这个问题就解决了。

路由组件特有的钩子

activated与deactivated是路由组件特有的钩子。activated是当一个路由组件被加载时被调用,deactivated是当一个路由组件被销毁时被调用。但是需要注意的是,这两个钩子需要配合缓存路由组件以一起使用keep-alive,没有keep-alive是无法触发的。

<template>
  <div>
    欢迎来到餐厅
    <input type="text" name="" id="">
  </div>
</template>

<script>
export default {
  name:'EatDemo',
  activated(){
    console.log('eat组件被调用');
  },
  deactivated() {
    console.log('eat组件被销毁');
  },
}
</script>

capture_20221010103038070.bmp

capture_20221010153916932.bmp

全局前置路由守卫

什么是路由守卫呢?其实就是相当于保安,在进入这个路由前,进行判断,看是否满足我们的要求,满足则放行,不满足就不放行。全局路由守卫就是在配置文件中设置路由守卫。 beforeEach是全局前置路由守卫,他里面传一个函数,函数里有三个参数。

router.beforeEach((to,from,next)=>{
    console.log(to,from ,next);
    next()
})

我们将这三个参数输出看一下

capture_20221010155529483.bmp 前两个都是对象,最后一个是函数。第一个对象表示要去的信息。第二个对象标识从哪里来的信息。next函数就是用来放行的函数。

现在来实现一个功能,点击第一个导航中的新闻与天气,不放行,点击其他的导航都放行。我们在新闻组件与天气组件的配置里写一个配置,写在meta中,isAuth为真表示不放行。

{
    name:'xinwen',
    path:'news',
    component:NewsDemo,
    meta:{
        isAuth:true
    }
},
{
    name:'tianqi',
    path:'weather',
    component:WeatherDemo,
    meta:{
        isAuth:true
    }
}

全局路由守卫:

router.beforeEach((to,from,next)=>{
    if(to.meta.isAuth===true){
        alert('不放行')
    }else{
        next()
    }
    
})

这样就实现了功能。

capture_20221010160525998.bmp 那么全局前置什么时候被调用呢?是在初始化-每次路由切换之前。

全局后置路由守卫

全局后置路由守卫是在初始化-每次路由切换之后调用,我们可以利用全局后置路由守卫实现切换组件后,给页面标题换成我们想要的。

首先给每个路由配置里添加meat配置,里面写title。之后利用全局后置路由守卫实现点击切换后,换标题。

router.afterEach((to,from)=>{
    console.log(from);
    document.title=to.meta.title || '啦啦啦'
})

我们看到全局后置守卫里的回调函数只有两个参数。这样功能就实现了。

路由守卫还有两种,一种是独享路由守卫,他只守卫一个路由,写在某个组件的路由配置里就好了。

beforeEnter:(to,from,next)=>{ 
  
}

还有一种是组件路由守卫

//通过路由规则,进入该组件时被调用
    beforeRouteEnter(to,from,next){
      console.log(to,from,next);
},
//通过路由规则,离开该组件时被调用
beforeRouteLeave(to,from,next){
  console.log(to,from,next);
}

他们写在组件中就可以了、