vue-router是一个插件库,专门用来实现SPA应用

一、SPA应用

  1. 单页web应用(single page web application)
  2. 整个应用只有一个完整的页面
  3. 点击页面中的导航链接不会刷新页面,只会做页面的局部更新
  4. 数据需要通过ajax请求获取

二、路由

1. 什么是路由?

  1. 路由就是一组映射关系(key-value)
  2. key为路径,value可能是function或component

2. 路由分类

  1. 后端路由:value是function,用于处理客户端提交的请求

工作过程:服务器收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据

  1. 前端路由:value是component,用于页面展示

工作过程:当浏览器的路径改变时,对应的组件就会显示

三、基本使用

  1. 安装

vue-router4只能在vue3中使用

vue-router3可以在vue2中使用

npm i vue-router@3
  1. 应用插件
Vue.use(VueRouter)
  1. 编写router配置项
  • 提前写好两个组件,MyAbout,MyHome,
  • 创建router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import MyAbout from '../pages/MyAbout.vue'
import MyHome from '../pages/MyHome.vue'
//创建一个路由器
export default new VueRouter({
    routes: [{
        path: '/about',
        component: MyAbout
    },
    {
        path: '/home',
        component: MyHome
    }
    ]
})
  • 实现切换:

原先使用a标签,vue中使用router-link

<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
  • 指定展示位置
<router-view>我是默认内容</router-view>
  1. 注意点
  • 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹
  • 通过切换,“隐藏”了的路由组件,默认是被销毁的,需要时的时候再去挂载
  • 每个组件都有自己的$route属性,里面存储着自己的路由信息
  • 整个应用只有一个router,可以通过组建的$router属性获取到

四、多级(嵌套)路由

  1. 配置路由规则,使用children配置项,children里面的path就不要再写最前面的斜杠/
//该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import MyAbout from '../pages/MyAbout.vue'
import MyHome from '../pages/MyHome.vue'
import MyNews from '../pages/MyNews.vue'
import MyMessage from '../pages/MyMessage.vue'
//创建一个路由器
export default new VueRouter({
    routes: [{
        path: '/about',
        component: MyAbout
    },
    {
        path: '/home',
        component: MyHome,
        //子路由
        children:[
            {
                path:'news',
                component:MyNews
            },
            {
                path:'message',
                component:MyMessage
            }
        ]
    },
    
    ]
})
  1. 跳转(要写完整路径,加上自己的上一级路径):
<router-link to="/home/news" class="list-group-item>news</router-link>

五、路由的query参数

1. to的字符串写法

<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>

2. to的对象写法

<router-link
          :to="{
            path: '/home/message/detail',
            query: {
              id: m.id,
              title: m.title,
            },
          }"
        ></router-link>

3. 接收参数

<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>

六、路由命名

1. 作用

简化路由的跳转

2. 给路由命名

{
        path: '/home',
        component: MyHome,
        //子路由
        children: [
          {
                name:'message',
                path: 'message',
                component: MyMessage,
                children: [
                    {
                        //路由命名
                        name:'xiangqing',
                        path: 'detail',
                        component: MyDetail
                    }
                ]
            }
        ]
}

3. 简化跳转

//原先
<!-- <router-link to="/home/message/detail">{{m.title}}</router-link> -->
// 简化后
<!-- <router-link :to="{name:"xiangqing"}">{{m.title}}</router-link> -->
// 简化写法配合传递参数
<router-link
          :to="{
            name: 'xiangqing',
            query: {
              id: m.id,
              title: m.title,
            },
          }"
          >{{ m.title }}
</router-link>

七、路由的params参数

  1. 在配置路由规则的index.js文件里,在path项中添加占位符
 children: [ 
                    // params参数
                    {
                        //路由命名
                        name: 'xiangqing',
                        path: 'detail/:id/:title',//使用占位符声明params参数
                        component: MyDetail
                    }
            ]
  1. 使用
  • 注意:对象写法中不可以写path项,只能使用 name
// 路由携带params参数,to的字符串写法
<router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>
//路由携带params参数,to的对象写法
<router-link
          :to="{
            name: 'xiangqing',
            params: {
              id: m.id,
              title: m.title,
            },
          }"
          >{{ m.title }}
</router-link>
  1. 接收参数
<li>消息标题:{{$route.params.title}}</li>

八、路由的props配置

  1. 第一种写法:

值为对象,对象中的所有key-value都会以props形式传递给Detail组件

  props:{
          a:1,b:'2'
        }

接收并使用:

<template>
    <li>a:{{a}}</li>
    <li>b:{{b}}</li>
</template>
<script>
  props:['a','b']
</script>
  1. 第二种写法:

值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数以props形式传递给Detail组件

path: 'detail/:id/:title',
props:true

接受并使用:

<template>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
</template>
<script>
    props: ["id", "title"],
</script>
  1. 第三种写法(最强大):

值为函数

props($route) 
{
     return { id: $route.query.id, title: $route.query.title }
}
// 或者使用解构赋值写法
props({query}) 
{
     return { id: query.id, title: query.title }
}

接受并使用:

<template>
    <li>消息编号:{{ id }}</li>
    <li>消息标题:{{ title }}</li>
</template>
<script>
    props: ["id", "title"],
</script>

九、<router-link>的replace属性

  1. 作用:控制路由跳转时操作浏览器历史纪录的模式

也就是浏览器的这个地方,控制上一页和下一页

img

  1. 浏览器的历史纪录有两种写入方式,分别为pushreplacepush是追加历史记录,replace是替换掉当前的历史记录,默认为push,想要切换成replace,则:
<router-link replace .....></router-link>

栈模式,指针指向顶部,点击回退按钮,指针向下移,点击享有的按钮,指针上移

img

十、编程式路由导航

  1. 作用:不借助<router-link></router-link>,让路由跳转更加灵活
  2. $router的五个API
this.$router.push({
        name: "xiangqing",
        query: {
          id: m.id,
          title: m.title,
        },
});
this.$router.replace({
        name: "xiangqing",
        query: {
          id: m.id,
          title: m.title,
        },
});
//回到上一页
this.$router.back();
//前进一页
this.$router.forward();
//传递数字,证书表示前进,负数表示回退
this.$router.go(3);

十一、缓存路由组件

  • 问题:

在切换组件的时候,呗“隐藏”的组件其实是被销毁了,再次切换回来的时候是重新挂载的,但是如果组件中有输入框,被切换走后在切换回来,用户输入的内容就会被清空,为了解决这一问题,可以使用缓存路由

  • 想要缓存哪一个组件里的内容,就在他所在的组件中(可以说是他的父组件)操作
  • 使用<keep-alive>标签
<keep-alive>
        <router-view></router-view>
</keep-alive>
  • 加上include="组建的名字name"标签,可以指定缓存哪个组件里的内容,如果不写,则默认缓存全部组件
<keep-alive include="MyNews">
        <router-view></router-view>
</keep-alive>
  • 作用:让不展示的组件保持挂载,不被销毁

十二、两个新的生命周期钩子

  1. 引出问题:切换组件,隐藏的组件被销毁,显示的组件被挂载,如果我们希望缓存组件中的数据,就会使用<keep-alive>来让组件保持挂载,不被销毁。但如果组件中有定时器,我们希望在不展示的时候将他清除,但因为使用了路由缓存,没法在调用beforeDestroy()钩子来清除定时器,所以我们引出下面两个路由组件中独有的两个钩子:activated()deactivated()
  2. 两个钩子的作用:用于捕获路由组件的激活activated()和失活deactivated()状态
  3. 示例
<template>
  <div>
    <ul>
      <li class="change" :style="{ opacity }">我的样式要变化</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "MyNews",
  data() {
    return {
      opacity: 1,
    };
  },
  //   beforeDestroy(){
  //     console.log("news被销毁了");
  //     clearInterval(this.timer);
  //   },
  //   mounted(){
  //     this.timer=setInterval(()=>{
  //         this.opactiy-=0.1;
  //         if(this.opacity<=0){
  //             this.opacity=1;
  //         }
  //     })
  //   },
  //路由组件独有的两个生命周期钩子
  //激活
  activated() {
    console.log("news被激活了");
    this.timer = setInterval(() => {
        console.log(this.opacity)
      this.opacity -= 0.1;
      if (this.opacity <= 0) {
        this.opacity = 1;
      }
    },16);
  },
  //失活
  deactivated() {
    console.log("news被失活了");
    clearInterval(this.timer);
  },
};
</script>

十三、路由守卫

引出问题:有的时候查看东西需要权限,比如要登陆,或者身份必须得是管理员才能查看等,这时候就需要路由守卫

1. 全局路由守卫

  1. 全局前置路由守卫

初始化的时候执行,每次路由切换之前被调用

router.beforeEach((to, from, next) => {
    //to表示要去往的,from表示从哪来
    console.log(to, from)
    if (to.meta.isAuth) {//判断是否需要授权
        //只有当学校的名字十hky时才会放行,切换路由
        if (localStorage.getItem('school') === 'hky') {
            next();
        } else {
            alert('学校名不对,无权限访问')
        }

    } else {
        //如果不需要授权,直接放行
        next()
    }
})

要给自己配制的路由规则中添加meta项,表示如果要切换到该路径,需要授权

meta: { isAuth: true},
  1. 全局后置路由守卫

初始化时执行,每次路由切换后执行

router.afterEach((to, from) => {
    console.log("ddddd", to, from)
    if (to.meta.title) {
        document.title = to.meta.title
    } else {
        document.title = 'route_test'
    }
})

更改的是这个地方的title

img

2. 独享守卫beforeEnter

在配置路由规则的时候写,只有前置,没有后置

meta: { isAuth: true, title: '新闻' },
beforeEnter(to, from, next) {
   console.log("beforeEnter被调用")
    if (to.meta.isAuth) {//判断是否需要授权
    //只有当学校的名字十hky时才会放行,切换路由
         if (localStorage.getItem('school') === 'hky') {
             next();
          } else {
              alert('学校名不对,无权限访问')
           }

      } else {
             //如果不需要授权,直接放行
             next()
       }
}

3. 组件内守卫

//进入守卫,通过路由规则,进入该组件时被调用
beforeRouteEnter(to,from,next){},
//离开守卫,通过路由规则,离开该组件时被调用(不常用)
//但要注意,如果还想实现切换到某一路径后,标签页的名字跟着一起更改,就不可以把逻辑写在这里,
//应该写在全局后置守卫中
beforeRouteLeave(to,from,next){}

十四、路由器的两种工作模式

  1. 对于一个url来说,什么是hash指?

​ #及其后面的内容就是hash指

  1. hash指不会包含在http请求中,不会带给服务器
  2. hash模式:
  • 地址中永远带着#号,不美观
  • 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
  • 兼容发行较好
  1. history模式
  • 地址干净,美观
  • 兼容性和hash模式相比略差
  • 应用部署上线时需要后端人员支持,解决刷新页面服务端404问题

生活感悟

这周进度比较快,看视频看的也比较仔细,只是有时候犯懒看视频的时候不想记笔记,导致今天写博客总结的时候发现有好几节内容只写了个标题,代码也不知道写哪去了,我又只得回去再看一遍视频,以后学习一定不能这样,还是得多敲。
引用舍友朋友圈的一句话:学计算机的,代码跑不动,我也跑不动
求代跑(无偿)

学习计划

这一阶段的学习计划就剩10天了,这周把TS学完,复习一下Vue,另外Python也得好好学学,下周好像要考试。还有时间的话把js高级也得复习一下,忘完了快

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐