您现在的位置是:首页 >技术杂谈 >Vue(路由插件)网站首页技术杂谈

Vue(路由插件)

DF-vegan 2024-06-26 14:24:01
简介Vue(路由插件)

一、介绍路由

1. 路由就是一组key-value的对关系,多个路由需要经过路由器进行管理

2. 主要应用在SPA(单页面应用) 

  • 在一个页面展示功能之间的跳转

特点:

  • 当跳转时候不进行页面刷新
  • 路径随着变化
  • 展示区变化但是不开启新的页签      

 3. 跳转规则:

  • 点击指定模块 
  • 路径变化(加后缀)
  • router监测:路径变化
  • 展示对应的路径的组件内容
  • 如果不存在路由存储的路径,页面就不会进行展示

 二、路由使用(十之前使用的都是声明式路由导航)

1. 安装路由

vue-router4(默认版本)只能在vue3中使用

vue-router3 对应 vue2

此处使用vue2进行了解,所以基于vue2进行安装

npm i vue-router@3

2. 插件的引入和使用(入口文件中)

// 引入vue-router
import VueRouter from 'vue-router'
//使用vue-router
Vue.use(VueRouter)

3.配置路由

  • 引入安装的路由
  • 引入各个组件
  • 暴露路由器:此处注意配置routes
//该文件专门创建整个应用中路由器
import VueRouter from "vue-router";
// 引入组件
import About from '../commponents/About'
import Home from '../commponents/Home'
// 创建并暴露一个路由器
export default new VueRouter({
  routes: [
    {
      path: '/about',
      component:About
    },
    {
      path: '/home',
      component:Home
    },
]


})

4. 声明式导航进行展示(简单实现情况下使用)

  • router-link链接包裹需要导航的按钮或者模块(可以理解router-link就是a标签
  • to:表示从当前页面跳转到哪个组件中去:值是路由路径,因为to中的值都是js表达式,所以进行绑定
  • active-class:导航被激活时候的样式

在不使用传参和name属性的情况下都不需要对to进行绑定

  <router-link class="list-group-item" active-class="active" to="/about">About</router-link>
  • 链接路由路径之后进行展示:利用标签放在需要展示的部分
  <router-view></router-view>

 

三、使用路由的注意点

1. 关于组件分类

  • 一般(公共)组件:放在components文件夹
  • 路由组件:由路由器渲染的组件叫做路由组件放在pages文件夹

2. 路由组件的销毁和挂载

  • a组件切换成b组件
  • a组件被销毁
  • b组件完成挂载

3. 路由组件都出现了路由和路由器

  • 路由就是自身相关的路由规则(每个路由都不同)
  • 路由器在每个路由组件理都有并且相同
//配置代码的挂载之后取得路由
//a路由组件的
window.aboutRoute = this.$route
window.aboutRouter = this.$router
//b路由组建的
window.homeRoute = this.$route
window.homeRouter = this.$router

 四、嵌套路由(配置使用区别于基本使用)

1. 基于安装路由并使用插件的基础上进行配置

此处多出来一个新的子级配置项:children

配置每个路由的路径和组件方式还是相同

routes: [
  // about和home是一级路由
  { 
    path: '/about',
    component:About
  },
  {
    path: '/home',
    component: Home,
    // 二级路由规则
    children: [
      {
        path: 'news',
        component:News
      },
      {
        path: 'message',
        component:Message
      },
    ]
  },
]

2. 跳转路由:带爹路径

  • 在路由组件中进行链接子级路由
  • 注意此处router-link链接跳转的to不能直接写子级路径,需要带父级路径
 <router-link class="list-group-item " active-class="active" to="/home/news">News</router-link>
 

五、路由传参query

  • 当进行路由进行跳转的时候,如果某个路由组件需要传递参数,这时候就可以用到参数链接
  • 开发中:路由的嵌套一般只会到三四级,不会更多
  • 注意:如果一个组件中存在多个消息,每个消息都需要传递出来一个新的展示组件,这时候使用路由组件就比较麻烦

1. 父组件进行遍历获取自身数据并展示在页面

//模板遍历
 <li v-for="m in messageList" :key='m.id'>
//组件中的数据
 data() {
    return {
      messageList:[
        {id:'001',title:'消息001'},
        {id:'002',title:'消息002'},
        {id:'003',title:'消息003'},
      ]
    }
  },

2. 配置路由规则 

//此处只展示三级路由规则
    {
          path: 'message',
          component: Message,
          // 三级路由进行传参
          children: [
            {
              path: 'detail',
              component:Detail
            }
          ]
        },

3. 创建一个展示组件获取参数

此处是利用$route的query参数进行接收和传递

传递:在父级组件中链接路由路径的时候利用query添加参数

  • 字符串写法:注意获取到的参数使用模板字符串进行包裹
  • 对象写法:直接布置路径和query参数,一对象方式进行配置数据

注意:此时路由链接展示在li标签中,可以直接获取到遍历的数据,但是to需要进行绑定才能识别js格式代码

 <li v-for="m in messageList" :key='m.id'>
            <!-- 注意此处传递信息通过获取数据进行传递 -->
            <!-- 通过模板写法将里面字符都变成模板,模板里面参杂的js语用符号包裹 -->
            <!-- 想要知道获取的是上面遍历数据就得添加: -->
            <!-- 跳转路由并携带query参数,to的字符传传参写法 -->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>



            <!-- 跳转路由并携带query参数,to的对象写法 -->
            <router-link :to="{
              path:'/home/message/detail',
              query:{
                id:m.id,
                title:m.title
              }
            }">{{m.title}}</router-link>&nbsp;&nbsp;
          </li>

获取:在获取参数组件中利用$route.query.name进行获取(每个组件中都有自己的route)

//直接利用组件参数进行获取
  <ul>
    <li>消息编号:{{$route.query.id}}</li>
    <li>消息标题:{{$route.query.title}}</li>
  </ul>

六、命名路由

1. 给每一个路由起一个名字

  routes: [
    { 
      name:'guanyu',
      path: '/about',
      component:About
      children: [
            {
              name:'xiangqing',
              path: 'detail',
              component:Detail
            }
          ]
        },
      ]
    },
]

2. 路由通过名字进行链接

  • 如果使用字符串格式链接名字时候需要对to进行绑定并将name配置包裹在{}中
  • 对象写法进行传递时候需要要配置name属性
//字符串写法
<router-link :to="{name:'guanyu'}">About</router-link>

//对象写法
 <router-link :to="{
       name:'xiangqing',
       query:{
           id:m.id,
           title:m.title
        }
}">{{m.title}}</router-link>

七、params参数传递

1. 配置路由声名接收params参数

创建新的路由配置:注意path需要绑定传入的数据名字

 {
      path: '/home',
      component: Home,
      children: [
        {
          path: 'news',
          component:News
        },
        {
          path: 'message',
          component: Message,
          children: [
            {
              name: 'xiangqing',
              // 占位符声名接收参数
              path: 'detail/:id/:title',
              component:Detail
            }
          ]
        },
      ]
    },

2. 传递参数

注意传递的时候字符串写法直接使用路径方式写法进行写参数(不建议)

建议写成对象格式:如果写成params参数传递对象格式,必须使用name,不能使用path

<!--params参数传参:to的字符串写法-->
<router-link :to="`/home/message/detail/666/你好啊`">固定参数跳转</router-link>

<!--params参数传参:to的对象写法-->
 <router-link :to="{
              name:'xiangqing',
              params:{
                id:666,
                title:'你好'
              }
}">{{m.title}}</router-link>

3. 接收参数

$route.params.id
$route.params.title

八、路由组件如何读取传递进来的参数

为什么关注以上问题:

  • 当传递进来的参数包含多个,那么如何简化接收参数代码
$route.params.id
$route.params.title
$route.params.id2
$route.params.title2
$route.params.id3
$route.params.title3

props:外部传给路由获取参数组件的方式

首先传递参数,以下都会使用到此参数传递效果(第二种种通过params传递,最后函数式使用query进行传递)

 <router-link :to="{
              name:'xiangqing',
              params:{
                id:666,
                title:'你好'
              }
}">{{m.title}}</router-link>
:to="{
      path:'/home/message/detail',
      query:{
      id:m.id,
      title:m.title
  }

1. 在路由配置中添加新的配置并在获取参数组件处进行接收

注意数据是由路由中props进行控制


 children: [
    {
      name: 'xiangqing',
      path: 'detail',
      component: Detail,
   // 第一种写法,值为对象,该对象的所有key-value都会通过props的形式传给detail组件
      props: {
          a:1,
          b:'hello'
      }
}
//组件中首先接收,然后在模板中直接使用
props:['a','b'],//对象形式

//使用
  <li>消息编号:{{a}}</li>
  <li>消息标题:{{b}}</li>

使用较少,传递的是固定数据

2. 在路由中配置布尔值(params参数传递)

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

 children: [
    {
      name: 'xiangqing',
      // 占位符:声名接收参数
      path: 'detail/:id/:title',
      component: Detail,
    //第二种写法:布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给detail组件
     props:true
}

然后再组件中进行接收,直接接收到的就是绑定的数据

并可以直接使用

//首先进行接收
props:['id','title'],//布尔值形式
//模板中直接使用
 <li>消息编号:{{id}}</li>
 <li>消息标题:{{title}}</li>

3. 路由匹配值中使用参数为函数式(query参数传递)

  • 直接写死函数形式


 children: [
    {
      name: 'xiangqing',
      path: 'detail',
      component: Detail,
      props() {
         return{id:'666',title:'你好'}
 }
}
  • 可以动态获取其中数据(传递参数$route)


 children: [
    {
      name: 'xiangqing',
      path: 'detail',
      component: Detail,
      props($route) {
         return{
             id:$route.query.id,
             title:$route.query.title}
     }
}
  • 优化参数:多层结构赋值


 children: [
    {
      name: 'xiangqing',
      path: 'detail',
      component: Detail,
      //结赋值连续写法:先解构参数来源query,再解构id和title
      props({query:{id,title}}) {
          return{id,title}
     }
}

此参数不仅动态,还可以路由添加

九、路由组件的历史记录

历史记录保存方式:栈的方式进行保存历史记录

默认push保存方式:指针默认指向最上层

 replace保存方式:新的地址总是替换最上层的地址

 replace的书写方式:直接再router-link绑定路由处进行添加标签属性

//此处对比了replace的两种写法和绑定路径和名字的方式
<router-link :replace="true" :to="{name:'guanyu'}">About</router-link>
<router-link replace to="/home">Home</router-link>

十、编程式路由导航

声明式导航必须借助router-link的to属性进行跳转(router-link就是a标签):必须点击

某种情况不能使用router-link:

  • 导航块使用的是button而不是a标签就不能使用
  • 定时器倒计时进行展示

1. 使用导航模块按钮进行展示编程式导航

此处使用了路由器($router)的历史记录方式

然后将传递参数和链接路由路径/名字的对象方式相同

  • 注意:传递的参数来自于模板被li包裹所遍历的,此处不用注意,只用看方法
//创建代码按钮:里面绑定事件和事件的回调
 <button @click="pushShow(m)">push查看</button>
 <button @click="replaceShow(m)">replace查看</button>

//设置事件回调并传递参数
 methods: {
      pushShow(m){
        // 执行push历史记录
        this.$router.push({
        name:'xiangqing',
        query:{
          id:m.id,
          title:m.title
        }
      })
    },
      replaceShow(m){
        // 执行replace历史记录
        this.$router.replace({
        name:'xiangqing',
        query:{
          id:m.id,
          title:m.title
        }
      })
    }
  },

十一、路由组件历史纪录的跳转api

 前进

  <button @click="forward">前进</button>

//方法
 forward(){
        this.$router.forward()
      },

后退

<button @click="back">后退</button>

//方法
back(){
       this.$router.back()
      },

指定步数:此处指定后退2步

  <button @click="test">测试go</button></div>

//方法
 test(){
        // 注意此处的go需要使用参数(表示执行几步)
        this.$router.go(-2)
      }

十二、缓存路由组件

当路由组件进行切换之后,之前组件就会销毁

 如何让路由组件切换之后输入的内容还能保存

1. 保持活跃标签<keep-alive></keep-alive>(放置在最外层链接路由展示位置)

:如果直接使用以上标签,后面会出现的路由组件都会缓存

 

 <keep-alive>
         <router-view></router-view>
 </keep-alive>

2. 缓存指定组件:添加新的配置:include

缓存指定路由组件,注意进行绑定,一位内使用的是js格式代码

此处缓存的名字使用的是组件名字,而不是路由名字

<keep-alive :include='["News","Message"]'>
              <router-view></router-view>
</keep-alive>

十三、新的生命周期钩子(激活失活)

挂载组件切换被销毁:实现路由组件缓存之后:

  • 缓存的input组件内容会存在

  • 组件中定时器的内容会持续更新(此时不需要进行持续更新)

使用激活和失活生命周期钩子(放在展示组件内)

activated(切换查看的会激活)   /   deactivated(切走之后会失活)

在展示组件内将不需要缓存的内容进行激活和失活操作

 // 激活
  activated() {
    // console.log('news组件被激活');
      this.timer = setInterval(() => {
      console.log('@');
        this.opacity -= 0.01;
        // 此处注意:js不会计算小数:如果opacity的值小于等于0
        if (this.opacity <= 0) this.opacity = 1;
      }, 16);
  },



  // 失活
  deactivated() {
    // console.log('news组件失活');
    clearInterval(this.timer)
  },

十四、全局路由守卫(权限控制):路由器中进行配置router.beforeEach

路由点击之后会展示不同的组件

但是有的路由组件必须是指定账户或者信息才能进行查看

配置前置路由守卫

  1. 首先将路由器中的规则进行命名
  2. 利用beforeEach-api全局前置路由组件守卫(开启就需要进行参数设置)
    1. 参数包含to,from,next
    2. to表示准备去哪个组件
    3. from来自于那个组件
  3. 暴露路由器
  4. 执行next方法:继续执行(就是在这里配置相关守卫通过信息)
//命名规则
const router = new VueRouter({}

//配置全局前置路由守卫
router.beforeEach((to, from, next) => {
    next()
}


//暴露路由器
export default router

前置路由守卫:router.beforeEach中进行判断什么时候放行并继续执行

注意此处使用判断条件是准备去往的路径(此处自行设置)

以及本地用户是否匹配

router.beforeEach((to, from, next) => {

if(to.path === '/home/news' || to.path === '/home/message'){
//以上的判断语句也可以直接使用路由名字进行配置
//  if (to.name === 'xinwen' || to.path === 'xiaoxi')
    if (localStorage.getItem('school') === 'xlf') {
        next()
      } else {
        alert('学校名不对,无权限查看')
      }
  }
}

路由跳转条件如果有很多代码冗余问题(解决)

  •  路由中配置路由元属性:meta对象中(key值为true表示路由是否需要路由权限判断)

  • 哪个路由中需要就放在哪个路由中:调整值为true
  meta: { isAuth: true, title:'详情'},  
  • 然后在守卫中配置判断条件就根据meta中isAuth进行判断是否需要权限

router.beforeEach((to, from, next) => {

if(to.meta.isAuth){
//以上的判断语句也可以直接使用路由名字进行配置
//  if (to.name === 'xinwen' || to.path === 'xiaoxi')
    if (localStorage.getItem('school') === 'xlf') {
        next()
      } else {
        alert('学校名不对,无权限查看')
      }
  }
}

后置路由守卫,没有next():使用在title属性和每个组件对应

每次路由切换之后被调用

  • 每个要切换的路由中配置了路由元信息:meta:{title:'自己命名'}
  • 然后路由守卫中就可以通过meta进行获取
  • 进行判断:解决页面初始没有名字问题(也可以直接在html主要进行修改)
 router.afterEach((to, from) => {
    document.title = to.meta.title || '路由守卫系统'  
})  

十五、独享路由守卫(beforeEnter)

某一个路由单独需要守卫

直接在路由中进行配置(放在需要进入的路由组件原则内)

beforeEnter: (to, from, next) => {
     if (to.meta.isAuth) {
        if (localStorage.getItem('school') === 'xlf') {
                next()
             } else {
                alert('学校名不对')
            }
          } else {
              next()
        }
  }

如果还需要进行全局后置路由守卫,重新打开

 router.afterEach((to, from) => {
    document.title = to.meta.title || '路由守卫系统'  
})  

十六、组件内路由守卫

  • beforeRoteEnter:通过路由规则进入该组件时候调用

  • beforeRoteLeave:通过路由规则离开此组件时候调用

顾名思义,在组件种单独设置路由守卫:

都包含三个参数,每次执行当前跳转需求之后就添加next()继续往下

添加权限设置组件内路由守卫

注意前提就是路由规则配置了meta还有本地存储的信息是否合适

 beforeRouteEnter (to, from, next) {
      if (to.meta.isAuth) {//控制是否需要权限:注意需要在路由配置中设置路由基本配置项meta
        // 限制权限
        if (localStorage.getItem('school') === 'xlf') {
            next()
         } else {
           alert('学校名不对,无权限查看')
         }
       } else {
       // 不是指定位置直接可以获取组件
          next()
      }
    },
 //  通过路由规则进入该组件
 beforeRouteLeave (to, from, next) {
   // 独享离开路由守卫
   console.log('app---  beforeRouteLeave');
        next()
}

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

#  :哈希

#包括后面的路径是哈希值:不会随着http请求发给服务器

比如:当访问一个服务器就会存在返回信息,但是哈希值存在就不会发送给服务器(只会获取到哈希值前的路径给服务器)

 

默认开启哈希工作模式:

可以在路由器配置中添加属性mode:默认hash,

如果修改则可以使history:mode:history

const router = new VueRouter({
  mode:'hash'
//各种路由
}

区别

两种工作模式呈现在页面路径的区别

hash的兼容性略强(并且在上线之后可以通过路径进行跳转路由)

 

十八、上线打包

当代码完成之后执行打包然后交给后端首选需要打包

打包:通过package.json中的buil语句运行

执行之后机会将工程文件生成一个dist文件夹中,里面都是html,css,js等文件

    "build": "vue-cli-service build",

上线:将打包生成的文件执行部署

  • 根据express框架生成一个服务器
// 首先合法包
npm init

//包命名
随便自己命名


//安装express
npm i express

//创建一个server.js服务器文件
//引入express
const express = require('express')
const history = require('connect-history-api-fallback');
const app = express()
    app.use(history())
    app.use(express.static(__dirname+'/static'))
    app.get('/person', (req,res) => {
      // 函数体
      res.send({
        name: 'tome',
        age:18
  })
})
app.listen(5005, (err) => {
  if(!err) console.log('服务器启动成功了');
})
  • 将静态资源dist文件中所有我呢见放在服务器包的static/public文件夹中
  • 注意history模式通过路径跳转路由时候就会404
  • 如果hsah进行通过路径跳转就不会404

如何即使用history又可以通过路径进行跳转

  • 后端人员服务器进行制作:

connect-history-api-fallback - npmProvides a fallback for non-existing directories so that the HTML 5 history API can be used.. Latest version: 2.0.0, last published: a year ago. Start using connect-history-api-fallback in your project by running `npm i connect-history-api-fallback`. There are 1401 other projects in the npm registry using connect-history-api-fallback.https://www.npmjs.com/package/connect-history-api-fallback

  • 根据文档提示:首先安装
npm install --save connect-history-api-fallback
  • 然后引入并应用在静态资源前面
//引入
const history = require('connect-history-api-fallback');
//使用
app.use(history())

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。