阅读 192

前端路由vue-router详解

一:认识路由及路由规则

随着Ajax的出现, 有了前后端分离的开发模式。

后端只提供API来返回数据, 前端通过Ajax获取数据, 并且可以通过JavaScript将数据渲染到页面中,

这样做最大的优点就是前后端责任的清晰, 后端专注于数据上, 前端专注于交互和可视化上。

随后在后端路由的基础上诞生了前端路由

有必要提前了解url的hashhtml5的history

vue-router前端路由的一种,是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。其官方网站: router.vuejs.org/zh/

vue-router是基于路由组件

  • 路由用于设定访问路径, 将路径和组件映射起来.
  • 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换

二:安装配置vue-router

vue-router常见安装方式有cdn、npm、vue cli(优先学习npm方式 熟悉webpack)

  1. 安装:

    例:npm install vue-router --save或者新版vue cli中vue ui可视化插件方式安装

    安装完成会在配置文件依赖描述中出现

    image-20210526124022157

    (填写依赖再npm也可行)

  2. 配置:

    在模块化工程中运用 项目结构:

    image-20210526130247762

    • 导入路由对象 并且调用Vue.use(Vue-router)

    • 创建路由实例 并且传入路由映射配置

    • 在vue示例中挂载创建的路由实例

      //router/index.js
      import Vue from 'vue'
      //配置路由相关的信息
      import VueRouter from 'vue-router'
      //通过Vue.use(插件),安装插件
      Vue.use(VueRouter)
      //配置映射关系
      const routes = []
      //创建VueRouter对象 
      const router = new VueRouter({
        //es6增强写法 
        routes
      })
      //导出后在main.js导入并挂载
      export default router
      复制代码
      //main.js
      //导入router 自动搜寻/index.js
      import router from './router'
      new Vue({
        router,  //挂载添加路由
        render: h => h(App)
      }).$mount('#app')
      复制代码

三:使用vue-router

  • 创建路由组件
  • 配置路由映射:组件和路径映射关系
  • 使用理由:通过<router-link><router-view>
//router/index.js
//配置映射关系
const routes = [
//例:
  {
    path: '/test',
    name: 'test',
    component: testView
  },
]
复制代码
//components/test.vue
//组件内容
<template >
  <div class="a">
    我是test组件
  </div>
</template>
<script>
//到处test组件
export default {
  name: "test",
};
</script>
<style scoped>
.a {
  width: 100px;
  height: 100px;
  background-color: red;
}
</style>
复制代码
//app.vue 组件内容挂上
<template>
  <div id="app">
      <router-link to="test"></router-link>
      <router-view></router-view>   
  </div>
</template>
复制代码

启动服务后可以使用路由访问:

image-20210526131220877

四:路由的默认值和修改为history模式

路由默认值

如何可以让路径默认跳到到首页, 并且<router-view>渲染首页组件呢?

只需要配置多配置一个映射就可以了 如下图:

//index.js
//配置映射关系
const routes = [
  {
    path:'/',
    redirect:'/default'
    //如果默认路径是/则重定向到/default
  },
]
复制代码

示例:

//views/default.vue
<template>
  <div>
    <h2>
        default默认首页面是我
    </h2>
  </div>
</template>

<script>

export default {
  name: 'defaultView',
  components: {
  }
}
</script>
<style>
h2{
    color: pink;
    font-size: 100px;
}
</style>
复制代码
//router/index.js
import Vue from 'vue'
//配置路由相关的信息
import VueRouter from 'vue-router'
import testView from '../views/testView.vue'
import defaultView from '../views/default.vue'
//通过Vue.use(插件),安装插件
Vue.use(VueRouter)
//配置映射关系
const routes = [
  {
    path:'/',
    redirect:'/default'
    //如果默认路径是/则重定向到/default
  },
  {
    path:'/test',
    name:'test',
    component:testView
  },
  {
    path:'/default',
    name:'default',
    component:defaultView
  }
]

//创建VueRouter对象 
const router = new VueRouter({
  //es6增强写法 
  routes
})

//导出后在main.js导入并挂载
export default router

复制代码
//App.vue
<template>
  <div id="app">
    <div>
        <router-link to="test">testView</router-link>
        <router-link to="default">default默认首页</router-link>
      <router-view></router-view>   
    </div>
  </div>
</template>
复制代码

效果图:

1111

history模式

改变路径的方式有两种:
复制代码
  • URL的hash

  • HTML5的history

    默认情况下, 路径的改变使用的URL的hash.

    使用HTML5的history模式, 非常简单, 进行如下配置即可:

const router = new VueRouter({
  //es6增强写法 
  routes,
  mode:'history'
})
复制代码

示例效果图:

image-20210530235729047

image-20210530235743190

可见hash的#已经不见了

五:router-link补充

其他属性:

  • tag: tag可以指定<router-link>之后渲染成什么组件, 比如上面的代码会被渲染成一个<li>元素, 而不是<a>
  • replace: replace不会留下history记录, 所以指定replace的情况下, 后退键返回不能返回到上一个页面中
  • active-class: 当<router-link>对应的路由匹配成功时, 会自动给当前元素设置一个router-link-active的class, 设置active-class可以修改默认的名称. 在进行高亮显示的导航菜单或者底部tabbar时, 会使用到该类. 但是通常不会修改类的属性, 会直接使用默认的router-link-active即可.

示例:

<template>
  <div id="app">
    <div>
        <router-link to="test" tag="button" replace >testView</router-link>
        <router-link to="default" tag="li">default默认首页</router-link>
        <router-link to="test" tag="button" replace active-class="active">testView222</router-link>
      <router-view></router-view>   
    </div>
  </div>
</template>
<style>
.active{
  background-color:red;
}
.router-link-active{
  color: blue;
}
</style>
复制代码

效果图:

11112

修改linkActiveClass

image-20210531180023607

image-20210531180110469

效果也同样可以显示出来

六、路由代码跳转

有时候, 页面的跳转可能需要执行对应的JavaScript代码, 这个时候, 就可以使用第二种跳转方式了 比如, 我们将代码修改如下:

image-20210531180643708

效果图:

111123

七、动态路由

在某些情况下,一个页面的path路径可能是不确定的,比如我们进入用户界面时,希望是如下的路径:

  • /user/aaaa或/user/bbbb
  • 除了有前面的/user之外,后面还跟上了用户的ID
  • 这种path和Component的匹配关系,我们称之为动态路由(也是路由传递数据的一种方式)。

Snipaste_2021-06-01_23-16-40

Snipaste_2021-06-01_23-32-08

Snipaste_2021-06-01_23-32-42

效果图:

![士大夫地方 (1)](gitee.com/wx_7585a018… (1).gif)

八、路由懒加载

方式一: 结合Vue的异步组件和Webpack的代码分析.

const Home = resolve => { require.ensure(['../components/Home.vue'], () => { resolve(require('../components/Home.vue')) })};
复制代码

方式二: AMD写法

const About = resolve => require(['../components/About.vue'], resolve);
复制代码

方式三(重点): 在ES6中, 我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.

const Home = () => import('../components/Home.vue')
复制代码

Snipaste_2021-06-02_20-13-09

九、嵌套路由

嵌套路由是一个很常见的功能

实现嵌套路由有两个步骤:

  1. 创建对应的子组件, 并且在路由映射中配置对应的子路由.

    Snipaste_2021-06-02_21-02-02

    Snipaste_2021-06-02_21-04-16

  2. 在组件内部使用<router-view>标签.

Snipaste_2021-06-02_21-06-17

效果图:

嵌套路由演示图

十、参数传递

传递参数的方式

准备工作:

为了演示传递参数, 我们这里再创建一个组件, 并且将其配置好

  • 第一步: 创建新的组件Profile.vue
  • 第二步: 配置路由映射
  • 第三步: 添加跳转的<router-link>

传递参数主要有两种类型: paramsquery

  • params的类型:
    • 配置路由格式: /router/:id
    • 传递的方式: 在path后面跟上对应的值
    • 传递后形成的路径: /router/123, /router/abc
  • query的类型:
    • 配置路由格式: /router, 也就是普通配置
    • 传递的方式: 对象中使用query的key作为传递方式
    • 传递后形成的路径: /router?id=123, /router?id=abc
传递参数方式一: <router-link>
//porfile.vue
<template>
  <div>
    <h2>profile页面是我</h2>
    <h3>userId:{{ $route.params.userId }}</h3>
    <h3>age:{{ $route.query.age }}</h3>
    <h3>size:{{ $route.query.size }}</h3>
  </div>
</template>

<script>
export default {
  name: "profile",
  components:{
  }
};
</script>
<style scoped>
h2{
  color: rgb(90, 184, 140);
  font-size: 100px;
}
</style>
复制代码
//router/index.js添加
const profile = () => import('../views/profile.vue')
  {
    path:'/profile/:userId',
    component:profile
  }
复制代码
//App.vue
<template>
  <div id="app">
    <div>
      <router-link to="/default">default</router-link>
      <div></div>
      <router-link to="/Home">Home</router-link>
      <div></div>
      <router-link :to="/profile/+userId">profile(params)</router-link>
      <div></div>
      <router-link :to="{
        path:'/profile/'+userID,
        query:{age:20,size:18}
      }">porfile(query)</router-link>
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {
      userId:234
    }
  },
}
</script>
<style>
</style>

复制代码

效果图:![路由参数传递 (1)](gitee.com/wx_7585a018… (1).gif)

传递参数方式二: JavaScript代码
//App.vue
<template>
  <div id="app">
    <div>
      <button>default</button>
      <button @click="toHome">Home</button>
      <button @click="toprofile">profile</button>
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {
      userId:234
    }
  },
  methods: {
    toHome(){
      this.$router.push('/Home/'+this.userId)
    },
    toprofile(){
      this.$router.push({
        path:'/profile/'+this.userId,
        query:{age:20,size:18}
      })
    }
  },
}
</script>

<style>
</style>

复制代码

获取参数

获取参数通过$route对象获取的.

在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新。

routeroute和router是有区别的

  • routerVueRouter实例,想要导航到不同URL,则使用router为VueRouter实例,想要导航到不同URL,则使用router.push方法
  • $route为当前router跳转对象里面可以获取name、path、query、params等

十一、导航守卫

导航守卫主要用来通过跳转或取消的方式守卫导航。

有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

(记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察$route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫)

  • vue-router提供的导航守卫主要用来监听监听路由的进入和离开的.
  • vue-router提供了beforeEachafterEach的钩子函数, 它们会在路由即将改变前和改变后触发.

beforeEach函数:

Snipaste_2021-06-03_21-27-17

示例:

前置守卫(guard)beforeEach为例来完成标题的修改(后置钩子(hook)afterEach暂时了解)

  • 在钩子当中定义一些标题, 可以利用meta(元数据)来定义
  • 其次, 利用导航守卫,修改我们的标题
    • 导航钩子的三个参数解析:
    • to: 即将要进入的目标的路由对象.
    • from: 当前导航即将要离开的路由对象.
    • next: 调用该方法后, 才能进入下一个钩子.
//router/index.js
 {
    path:'/default',
    name:'default',
    component:defaultView,
    meta:{
      title:'default'
    }
  }, {
    path:'/profile/:userId',
    component:profile,
    meta:{
      title:'profile'
    }
  }
router.beforeEach((to,from,next) => {
  //从from跳转到to
  document.title = to.matched[0].meta.title
  console.log(to);
  next()
} )
复制代码

效果图:

![导航守卫 (1)](gitee.com/wx_7585a018… (1).gif)

附加问题:

beforeEach中变量from定义了未引用 ealint代码校验报错解决:

// package.json
rules: {
    "no-unused-vars":"off"
}
复制代码

补充:

  1. 如果是后置钩子, 也就是afterEach, 不需要主动调用next()函数.
  2. 补充二: 上面我们使用的导航守卫, 被称之为全局守卫.
    • 路由独享的守卫
    • 组件内的守卫

Snipaste_2021-06-03_21-49-24

Snipaste_2021-06-03_21-51-55

具体参考Vue Router官网更新数据

十二、keep-alive

  • keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
    • 它们有两个非常重要的属性:
    • include - 字符串或正则表达,只有匹配的组件会被缓存
    • exclude - 字符串或正则表达式,任何匹配的组件都不会被缓存
  • router-view 也是一个组件,如果直接被包在 keep-alive 里面,所有路径匹配到的视图组件都会被缓存:
  • 通过create声明周期函数来验证
//App.vue
<keep-alive>
	<router-view>
    	<!-- 所有匹配到的视图子组件都会被缓存 -->
    </router-view>
</keep-alive>
复制代码

Snipaste_2021-06-03_22-17-55

Snipaste_2021-06-03_22-26-42

附:vue-router知识量化图

Vuejs知识量化

文章分类
前端
文章标签