Vue(路由插件)

一、介绍路由

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

Vue(路由插件)_第1张图片

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

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

特点:

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

Vue(路由插件)_第2张图片

 3. 跳转规则:

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

Vue(路由插件)_第3张图片

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

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进行绑定

  About
  • 链接路由路径之后进行展示:利用标签放在需要展示的部分
  

Vue(路由插件)_第4张图片

 

三、使用路由的注意点

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

Vue(路由插件)_第5张图片

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

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不能直接写子级路径,需要带父级路径
 News
 

五、路由传参query

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

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

//模板遍历
 
  • //组件中的数据 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格式代码

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

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

    六、命名路由

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

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

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

    • 如果使用字符串格式链接名字时候需要对to进行绑定并将name配置包裹在{}中
    • 对象写法进行传递时候需要要配置name属性
    //字符串写法
    About
    
    //对象写法
     {{m.title}}

    七、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

    
    固定参数跳转
    
    
     {{m.title}}

    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进行传递)

     {{m.title}}
    :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'],//对象形式
    
    //使用
      
  • 消息编号:{{a}}
  • 消息标题:{{b}}
  • 使用较少,传递的是固定数据

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

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

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

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

    并可以直接使用

    //首先进行接收
    props:['id','title'],//布尔值形式
    //模板中直接使用
     
  • 消息编号:{{id}}
  • 消息标题:{{title}}
  • 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保存方式:指针默认指向最上层

    Vue(路由插件)_第6张图片

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

    Vue(路由插件)_第7张图片

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

    //此处对比了replace的两种写法和绑定路径和名字的方式
    About
    Home

    十、编程式路由导航

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

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

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

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

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

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

    • 注意:传递的参数来自于模板被li包裹所遍历的,此处不用注意,只用看方法
    //创建代码按钮:里面绑定事件和事件的回调
     
     
    
    
    //设置事件回调并传递参数
     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

     前进

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

    后退

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

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

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

    十二、缓存路由组件

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

    Vue(路由插件)_第8张图片

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

    1. 保持活跃标签(放置在最外层链接路由展示位置)

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

    Vue(路由插件)_第9张图片

     

     
             
     

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

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

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

    
                  
    

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

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

    • 缓存的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的兼容性略强(并且在上线之后可以通过路径进行跳转路由)

    Vue(路由插件)_第10张图片

     

    十八、上线打包

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

    打包:通过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())

    你可能感兴趣的:(vue.js,前端,javascript)