12-Vue-Router前端路由

18 篇文章 0 订阅

一、前端路由

前端路由是指由前端控制URL到页面的映射关系,即改变URL时,页面不进行刷新。

改变URL通常有以下两种方式:

1.1 URL的hash模式

URL的hash是指锚点(#),本质是改变window.location的href属性,可以直接通过location.hash改变href属性,但页面不发生刷新。

在这里插入图片描述

1.2 HTML5的history模式

1.2.1 pushState

也可以通过history.pushState改变URL,页面也不会发生刷新。

类似一个栈结构,通过pushState入栈,back出站:
在这里插入图片描述

1.2.2 replaceState

在pushState方法下,可以使用浏览器的回退按钮,如果使用history.replaceState改变URL,是不可以使用回退按钮的,此时直接替换了URL。
在这里插入图片描述

1.2.3 go

  • history.back()等价于history.go(-1)

  • history.forward()等价于history.go(1)

  • 相当于浏览器界面的前进和后退
    在这里插入图片描述

二、vue-router

2.1 安装和使用

2.1.1 安装vue-router

npm install vue-router --save-dev

或者直接使用脚手架创建项目时,勾选vue-router

2.1.2 搭建router配置框架

在根目录下src中会多出一个router文件夹,其中包含一个index.js文件,在这个文件里用于定义前端路由,使用脚手架会自动生成(去掉了helloworld组件相关内容):

import Vue from 'vue'
import Router from 'vue-router'

// 通过vue.use(插件)安装路由插件
Vue.use(Router)
// 创建一个Router对象实例,并在routes中配置路由和组件的映射关系
// 再将对象导出,以便在vue实例中导入
export default new Router({
  routes: [
  ]
})

配置好后,在main.js中,导入router,在vue实例中挂载即可。
在这里插入图片描述

2.1.3 使用vue-router

  1. 首先在srccomponents文件夹中创建两个组件home.vueblog.vue

在这里插入图片描述

  1. src–>router文件夹中的index.js里导入这两个组件,并且在Router实例中配置对应的路径(跟在URL后)与组件名称,进行路由的映射:
import Vue from 'vue'
import Router from 'vue-router'
import Home from '../components/home'
import Blog from '../components/blog'

Vue.use(Router)
export default new Router({
  routes: [
    {
      path:'/home',
      component:Home
    },
    {
      path:'/blog',
      component:Blog
    }
  ]
})
  1. 页面会显示App.vue中的内容,所以在其中通过<router-link><router-view>使用路由:
<template>
  <div id="app">
    <router-link to='/home'>首页</router-link>
    <router-link to='/blog'>博客</router-link>
    <router-view></router-view>
  </div>
</template>
  • <router-link> : vue-router中内置的组件,会被渲染成一个<a>标签;
  • <router-view> : 根据当前路径,在页面上动态渲染出不同的组件。
  1. 配置默认路径

默认路径是指进入网站时首先渲染的页面内容,在这里如果想显示home组件的内容,只需要在路由中添加根路径’/'的映射重定向到/home路径下即可:

  routes: [
    {
      path:'/',
      redirect:'/home'
    }]
  1. 去掉URL中添加的/#

改变URL时,路径中间会加入一个#号,是因为此时默认使用的是hash模式。要去除#号,在Router实例中将hash模式改变为history模式即可。

//src-router-index.js
export default new Router({
  mode:'history',
  routes:[...]
})

2.2 router-link属性

<router-link>除了to属性外,还有一些常用的属性:

2.2.1 tag属性

将默认渲染的<a>标签,替换为指定的标签样式。

//指定为按钮样式    
	<router-link to='/home' tag='button'>首页</router-link>

2.2.2 replace属性

添加replace属性后,不可以使用浏览器的回退与前进按钮。

	<router-link to='/home' tag='button' replace>首页</router-link>

2.2.3 active-class属性

router-link对应的路由匹配成功后,当前元素会自动设置一个router-link-active的class,此时可以通过这个class名称修改当前匹配路由的样式。

<style>
.router-link-active {
	color:red;
}
</style>
  1. 如果觉得类名太长也可以在router-link标签上进行修改:
//修改为.active
	<router-link to='/home' tag='button' replace active-class='active'>首页</router-link>
  1. 如果想全局修改类型,需要在Router实例中添加属性:
//src-router-index.js
export default new Router({
  linkActiveClass:'active',
  routes: [..]
  })

2.3 使用方法跳转路由

在App.js中,也可以不使用router-link标签,通过方法来进行路由的跳转,这里首先直接定义两个button,绑定两个方法,在方法中使用内置的$router进行跳转操作:

  name:'App',
  methods: {
    homeclk(){
      this.$router.push('/home');
    },
    blogclk(){
      this.$router.push('/blog');
    }
  }

2.4 动态路由

如果需要在URL后跟的路径动态变化,就需要使用动态路由。比如在一个页面中,需要展示很多个产品,每个产品有对应的产品ID,通过URL+产品ID来实现动态跳转。

  1. components中添加一个prod.vue组件,定义产品页面。

  2. router-index.js中添加路由信息,这里的路径通过:参数拼接:

    {
      path:'/prod/:prodid',
      component:Prod
    }
  1. App.vue文件里的App实例-data属性中定义上面定义的参数prodid的值,并且在模板标签中通过v-bind动态绑定值传给router-link的to参数:
    <router-link :to="'/prod/'+ prodid" tag='button'>产品</router-link>
  1. 此时在页面中就激活路由时,URL后就会跟上data中传入的值:

在这里插入图片描述

  1. prod.vue页面可以在computed属性中定义prodID(),通过$route获取当前alive的路由($router是在index中创建的Router实例),再通过params.参数将data传入的值取出来。
<template>
...
    {{prodID}}
...
</template>
<script>
...
export default{
...
  computed: {
    prodID(){
      return this.$route.params.prodid
    }
  }
...
}
</script>

2.5 打包文件

通过npm run build打包生成的dist文件夹,通常包含以下内容:

在这里插入图片描述

其中:

  • .map文件用于输出代码的错误信息
  • css文件夹将所有css样式整合到1个.css文件中
  • js文件夹中,app代表开发时写的代码,manifest表示底层支撑代码(如包导入导出等),vendor表示第三方支撑代码(vue等)

2.5.1 路由的懒加载

打包时不同的页面都会在同一个js文件中,往往会导致文件过大,当从服务器请求时,加载时间过长,用户浏览器长时间等待的情况。

而懒加载就是将路由对应的组件打包成一个个的js代码块,访问的时候才加载对应的组件。在路由中,直接引用组件,如下:

    {
      path:'/prod/:prodid',
      component:() => import('../components/prod')
    }
或者
	const Prod = () => import('../components/prod')

再次打包,就会多出一个js文件:

在这里插入图片描述

懒加载的方式:

  1. (最古老的方式):Vue异步组件和webpack代码
const Prod = resolve => { require.ensure(['../components/Prod.vue'],() => { resolve(require('../components/Prod.vue')) })};
  1. AMD写法
const Prod = resolve => require(['../components/Prod.vue'], resolve);
  1. ES6写法
const Prod = () => import('../components/Prod.vue')

2.6 嵌套路由

有时会存在页面中再进行一次路由的情况,也就是组件中含有子组件,此时就需要嵌套路由。

  1. 首先在components文件夹里新建2个子组件,导出的名字分别为foodpet

在这里插入图片描述

  1. 在路由index.js文件中给父页面添加children属性,将子路由通过对象的方式传给父路由,并且同样可以设定默认显示的页面:
	{
      path:'/prod',
      component: () => import('../components/prod'),
      children: [
        {
          path: '/',
          redirect: 'food'
        },
        {
          path: 'food',
          component: () => import('../components/ProdFood')
        },
        {
          path: 'pet',
          component: () => import('../components/ProdPet')
        }
      ]
    }
  1. 在父组件prod.vue中的<template>里导入子组件的路由:
    <router-link to='/prod/food'>食品</router-link>
    <router-link to='/prod/pet' >宠物</router-link>
    <router-view></router-view>
  1. 显示效果:
    在这里插入图片描述

2.7 参数传递

在URL中可以传递参数,有以下两种方法:

2.7.1 params类型

  1. 通过冒号后跟参数配置路由格式
path:'/user/:userid'
  1. 在路径后跟上对应的参数值:
<router-link :to="'/user/'+ userid" tag='button'>用户</router-link>

2.7.2 query类型

当需要传入数据较多时,使用此方法。

  1. <router-link>中直接传入:
<router-link :to = "{path:'/mine',query:{name:'wht',age:18}}" tag="button">我的</router-link>

  1. 或者使用<button>按钮定义点击事件,在函数中通过$router传入参数:
      mineclk(){
        this.$router.push({
          path:'/mine,
          query:{
            name:'wht',
            age:18
          }
        })
      }

在页面中可以通过$route获取query的值:

    {{this.$route.query}}
    {{this.$route.query.name}}

效果如下:

在这里插入图片描述

三、NavigationGuard导航守卫

3.1 全局守卫

如果需要修改页面的标题,在一个一个页面中通过生命周期函数修改会太麻烦,所以借助导航守卫。

全局守卫分为beforeEach()(页面跳转前回调)和afterEach()(页面跳转后回调)。

  1. 首先在index.js路由中通过meta元数据来定义一些标题,比如:
    {
      path:"/mine",
      component: () => import('../components/Mine'),
      meta:{
        title:"我的"
      }
    }
  1. 利用beforeEach()函数在跳转前置回调,修改标题:
router.beforeEach((to, from, next) => {
  document.title = to.matched[0].meta.title
  next()
})

(无法显示:router需要const一个参数,不能直接导出)

函数解析,可以看做为前置钩子(hook):

  • to:即将要进入的路由对象;
  • from:当前导航即将要离开的路由对象;
  • next:调用方法后,才能进入下一个导航守卫
  • matched:针对有嵌套的路由,选取第一个meta作为值
  1. 后置钩子的写法如下:
router.afterEach((to, from) => { })

3.2 路由独享守卫

在Router实例中的routes对象中配置:

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

3.3 组件内守卫

在组件内,可配置如下守卫:

beforeRouteEnter:(to, from, next) => { }
beforeRouteUpdate:(to, from, next) => { }
beforeRouteLeave:(to, from, next) => { }

具体可参考官方教程

四、生命周期函数

在组件中,常用的有以下三种生命周期函数:

  1. create():创建组件的时候回调的函数;
  2. mounted():当组件的template挂载到DOM上会回调的函数;
  3. updated():当页面刷新时会回调的函数。

除此之外,可以用下图很好的表示:

img

五、keep-alive

使用<keep-alive>将动态的组件包裹起来,可以缓存组件实例,从而不会进行销毁(destroyed)。

当被包裹的组件动态切换时,keep-alive中的activateddeactivated这两个生命周期钩子函数将会被对应执行。

一个例子:

  1. App.js中,将动态显示的<router-view>使用<keep-alive>包裹起来:
<keep-alive><router-view></router-view></keep-alive>
  1. 在某个组件页面实例中,写上内部的activateddeactivated函数:
<script>
export default {
  name:'prod',
  data () {
    return {
    };
  },
    created() {
      console.log('created');
    },
    destroyed() {
      console.log('destroyed');
    },
    activated() {
      console.log('activated');
    },
    deactivated() {
      console.log('deactivated');
    },
}
</script>
  1. 运行,进入并离开组件页面,会发现没有执行destroyed函数:

在这里插入图片描述

5.1 keep-alive属性

keep-alive有2个重要属性:

  • include -字符串或正则表达式匹配到的组件才会被缓存
  • exclude-字符串或正则表达式匹配到的组件不会被缓存

例如:

    <keep-alive exclude="mine">
      <router-view></router-view>
    </keep-alive>

此时,组件名为mine的组件就不会被缓存,失去alive后生命周期会执行销毁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PP_L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值