Vue Router路由详解


1. 介绍

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由/视图表
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过渡系统的视图过渡效果
  • 细粒度的导航控制
  • 带有自动激活的 CSS class 的链接
  • HTML5 历史模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

vue-router路由模式:

  • hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History的浏览器。
  • history: 依赖 HTML5 History API 和服务器配置。
  • abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。

在这里插入图片描述

2. Vue Router 和 Vue 项目集成

安装:

如果在vue-cli创建项目时没有勾选上vue-router选项,此时就需要手动的来安装它:

npm i -S vue-router@3

注意在 Vue2 中要安装3的版本。

使用步骤:

  1. 在项目中的src目录下创建router文件夹,并在router文件夹下创建index.js文件:

    在这里插入图片描述

  2. 编写新创建的index.js文件,并且在入口文件main.js中注入路由

    这一步可以分为以下几小步:

    1. 引入相关库文件
    2. 以插件的方式添加,将VueRouter引入到Vue类中
    3. 定义渲染的组件
    4. 实例化路由对象及配置路由表
    5. 导出路由配置
    6. 在入口文件注入路由
    7. 在父组件App.vue文件中定义路由匹配成功后渲染的挂载点

    index.js:

    // 1.引入相关库文件
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    // 3.定义渲染的组件  === 视图组件 容器组件
    import Home from '@/views/Home.vue'
    
    // 2.以插件的方式添加,将VueRouter引入到Vue类中
    Vue.use(VueRouter)
    
    // 配置路由表
    const routes = [
      {
        // 匹配的路由
        path: '/home',
        // 匹配成功后要渲染的组件,这些组件会放在 src/views 目录下
        component: Home
      }
    ]
    
    // 4.实例化路由对象及配置路由表
    const router = new VueRouter({
      // 路由模式
      mode: 'history',
      // 路由规则表
      routes
    })
    
    // 5.导出
    export default router
    

    main.js:

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    
    new Vue({
      // 要通过 router 配置参数注入路由,从而让整个应用都有路由功能
      // router:router
      // 简写
      router,
      render: h => h(App)
    }).$mount('#app')
    

    App.vue:

    <template>
      <div>
        <!-- 定义路由匹配成功后渲染的挂载点 -->
        <router-view />
      </div>
    </template>
    
    <script>
    export default {
      components: {},
      data() {
        return {}
      },
      methods: {}
    }
    </script>
    
    <style lang="scss" scoped></style>
    

在这里插入图片描述

3. 声明式导航

描述:

它就是先在页面中定义好跳转的路由规则,vueRouter中通过 router-link组件来完成。

语法:

<router-link to="path"></router-link>
# router-link声明式导航,它编译成html的标签为a,在vue-router3版本中可以自定义设置
# router-link 标签中有三个参数
	+ to: string|{path:string,query:{},params:{}} 表示要跳转到的路由规则,这个参数是必填选项
    + tag: 默认编译生成的为a标签,可以自定义
    + activeClass 指定激活样式名称,默认名称为:router-link-active

使用:

首先在配置路由表,我们配置 home 页面和 about 页面:

index.js:

// 1.引入相关库文件
import Vue from 'vue'
import VueRouter from 'vue-router'

// 3.定义渲染的组件  === 视图组件 容器组件
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'

// 2.以插件的方式添加,将VueRouter引入到Vue类中
Vue.use(VueRouter)

// 配置路由表
const routes = [
  {
    // 匹配的路由
    path: '/home',
    // 匹配成功后要渲染的组件,这些组件会放在 src/views 目录下
    component: Home
  },
  {
    path: '/about',
    component: About
  }
]

// 4.实例化路由对象及配置路由表
const router = new VueRouter({
  // 路由模式
  mode: 'history',
  // 路由规则表
  routes
})

// 5.导出
export default router

然后在父组件中定义路由跳转规则:

App.vue:

<template>
  <div>
    <ul>
      <li>
        <router-link to="/home" tag="h3" activeClass="active">home</router-link>
      </li>
      <li>
        <router-link to="/about" activeClass="active">about</router-link>
      </li>
    </ul>
    <hr>
    <!-- 定义路由匹配成功后渲染的挂载点 -->
    <router-view />
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {}
  },
  methods: {}
}
</script>

<style lang="scss" scoped>
.active {
  color: red;
}
</style>

在这里插入图片描述

上面的案例中,我们在 router-link 标签中给入 to 参数的数据为字符串类型,我们还可以给入对象类型:

父组件(App.vue):

<template>
  <div>
    <ul>
      <li>
        <!-- 给入对象传参 -->
        <router-link :to="{ path: '/home', query: { id: 100 } }" activeClass="active">home</router-link>
      </li>
      <li>
        <!-- 给入字符串传参 -->
        <router-link to="/about?id=100" activeClass="active">about</router-link>
      </li>
    </ul>
    <hr>
    <!-- 定义路由匹配成功后渲染的挂载点 -->
    <router-view />
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {}
  },
  methods: {}
}
</script>

<style lang="scss" scoped>
.active {
  color: red;
}
</style>

在这里插入图片描述

注意:

  1. 给 to 参数传入对象类型的数据时,必须在 to 前面加冒号:
  2. 给 to 参数传入对象类型的数据中 query 类型是给地址栏传参用的,当然在给出字符串类型数据时也可以直接写入地址栏数据

4. 编程式导航

描述:

编程式导航就是通过js来实现路由跳转。

语法:

# 能回退 参数:String|Object
	+ this.$router.push("/login");
	+ this.$router.push({ path:"/login",query:{username:"jack"} });
# 不能回退 参数:String|Object
	+ this.$router.replace("/login");
	+ this.$router.replace({ name:'user' , params: {id:123} });
# n为数字,正数为前进,负数为回退
	+ this.$router.go( n );//

使用:

在上文声明式导航的基础上,用编程式导航如果要实现在 about 页面中点击按钮,3秒钟之后跳转到 home 页面,我们只需要修改 about 页面。

About.vue:

<template>
  <div>
    <h3>关于我们</h3>
    <button @click="goHome">点击到home</button>
  </div>
</template>

<script>
export default {
  methods: {
    goHome() {
      // 要求3秒钟之后跳转到 home 页面
      setTimeout(() => {
        // 通过this.$router对象中的push/replace方法完成路由切换
        // push/replace  string|object
        // push/push  string|object
        
        // this.$router.push('/home')
        this.$router.push({
          path: '/home',
          query: { id: 200 }
        })
      }, 3000)
    }
  }
}
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

案例——登录成功实现页面跳转:

配置路由(index.js):

// 1.引入相关库文件
import Vue from 'vue'
import VueRouter from 'vue-router'

// 3.定义渲染的组件  === 视图组件 容器组件
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
import Login from '@/views/Login.vue'

// 2.以插件的方式添加,将VueRouter引入到Vue类中
Vue.use(VueRouter)

// 配置路由表
const routes = [
  {
    // 匹配的路由
    path: '/home',
    // 匹配成功后要渲染的组件,这些组件会放在 src/views 目录下
    component: Home
  },
  {
    path: '/login',
    component: Login
  }
]

// 4.实例化路由对象及配置路由表
const router = new VueRouter({
  // 路由模式
  mode: 'history',
  // 路由规则表
  routes
})

// 5.导出
export default router

父组件(App.vue):

<template>
  <div>
    <router-link to="/login">login</router-link>
    <hr />
    <!-- 定义路由匹配成功后渲染的挂载点 -->
    <router-view />
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {};
  },
  methods: {},
};
</script>

<style lang="scss" scoped></style>

登录页面(Login.vue):

<template>
  <div>
    <h3>用户登录</h3>
    <hr />
    <div>
      <input v-model="username" />
    </div>
    <div>
      <input v-model="password" />
    </div>
    <div>
      <button @click="login">进入系统</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      username: 'admin',
      password: 'admin'
    }
  },
  methods: {
    login() {
      if (this.username === 'admin') {
        this.$router.replace('/home')
      } else {
        alert('登录失败')
      }
    }
  }
}
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

5. 重定向和404

描述:

重定向:用户在访问地址A的时候,强制用户跳转到地址C ,从而展示特定的组件页面。

404:用户访问的页面不存在时,显示的页面

实现方法:

配置路由表(index.js):

// 1.引入相关库文件
import Vue from 'vue'
import VueRouter from 'vue-router'

// 3.定义渲染的组件  === 视图组件 容器组件
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
import Login from '@/views/Login.vue'
import Notfound from '@/views/Notfound.vue'

// 2.以插件的方式添加,将VueRouter引入到Vue类中
Vue.use(VueRouter)

// 配置路由表
const routes = [
    {
        // 匹配的路由
        path: '/home',
        // 匹配成功后要渲染的组件,这些组件会放在 src/views 目录下
        component: Home
    },
    {
        path: '/about',
        component: About
    },
    {
        path: '/login',
        component: Login
    },
    // 路径为根时,重定向到 home 页面
    {
        path: '/',
        // 重定向
        redirect: '/home'
    },
    // 以上的规则都没有匹配成功,则返回404
    {
        path: '*',
        component: Notfound
    }
]

// 4.实例化路由对象及配置路由表
const router = new VueRouter({
    // 路由模式
    mode: 'history',
    // 路由规则表
    routes
})

// 5.导出
export default router

父组件(App.vue):

<template>
  <div>
    <ul>
      <li>
        <router-link to="/home">home</router-link>
      </li>
      <li>
        <router-link to="/about">about</router-link>
      </li>
      <li>
        <router-link to="/login">login</router-link>
      </li>
    </ul>
    <hr />
    <!-- 定义路由匹配成功后渲染的挂载点 -->
    <router-view />
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {};
  },
  methods: {},
};
</script>

<style lang="scss" scoped>
.active {
  color: red;
}
</style>

404页面(Notfound.vue):

注意:这个页面我们想要实现展示本页面之后 3 秒,路由重定向到 home 页面

<template>
  <div>404</div>
</template>

<script>
export default {
  // 在挂载完毕的生命周期函数中执行 3 秒钟后重定向到 home 页面
  mounted() {
    // setTimeout(() => {
    //   // 这种写法会让浏览器直接刷新,会结束上一个页面的所有任务,不用考虑销毁,工作中常用
    //   location.href = "/home";
    // }, 3000);

    let n = 1;
    this.timer = setInterval(() => {
      if (n++ >= 3) {
        this.$router.push("/home").catch(() => {});
      }
      console.log(n);
    }, 1000);
  },
  beforeDestroy() {
    // 如果计时器存在就清除计时器,防止浏览器卡顿
    this.timer && clearInterval(this.timer);
  },
};
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

注意:

注意编程式导航跳转到与当前地址一致的URL时会报错,但是这个报错不影响功能。

Vue Router 版本是3,这是版本 bug,可以修复,也可以不用管。

在这里插入图片描述

6. 嵌套路由

描述:

嵌套路由最关键在于理解子级路由的概念:

比如我们有一个/users的路由,那么/users下面还可以添加子级路由,如:

/users/index、/users/add等等,这样的路由情形称之为嵌套路由。

语法:

routes: [
  { 
      path: "/user", 
      component: User,
      //通过 children 属性为 /user 添加子路由规则
      children:[
          { path: "/user/index", component: Index },
          { path: "/user/add", component: Add },
      ]
  }
]

# 需要在 User组件中定义一个router-view 用于嵌套路由的渲染显示
<router-view></router-view>

案例:

  • 需求:

    登陆成功后会在 localStorage 中写入 token 值,并且跳转到后台管理页(admin),将后台汇总页和用户页作为子路由嵌套在后台管理页里。如果登录失败,后台管理页检测不到 localStorage 中的 token 值,会重新返回到登录页面,即登录失败,不会显示后台管理页。

  • 实现

    配置路由:

    // 1.引入相关库文件
    import Vue from 'vue'
    import VueRouter from 'vue-router'
    
    // 3.定义渲染的组件  === 视图组件 容器组件
    import Login from '@/views/Login.vue'
    import Admin from '@/views/Admin'
    import Dashboard from '@/views/Dashboard'
    import User from '@/views/User'
    
    // 2.以插件的方式添加,将VueRouter引入到Vue类中
    Vue.use(VueRouter)
    
    // 配置路由表
    const routes = [
        {
            path: '/login',
            component: Login
        },
        // 嵌套路由
        {
            path: '/admin',
            component: Admin,
            // 重定向
            redirect: '/admin/dashboard',
            // 嵌套路由
            children: [
                {
                    // 这里访问的是这个路径:/admin/dashborad
                    path: 'dashboard',
                    component: Dashboard
                },
                {
                    path: 'user',
                    component: User
                }
            ]
        }
    ]
    
    // 4.实例化路由对象及配置路由表
    const router = new VueRouter({
        // 路由模式
        mode: 'history',
        // 路由规则表
        routes
    })
    
    // 5.导出
    export default router
    

    父组件(App.vue):

    <template>
      <div>
        <!-- 定义路由匹配成功后渲染的挂载点 -->
        <router-view />
      </div>
    </template>
    
    <script>
    export default {
      components: {},
      data() {
        return {};
      },
      methods: {},
    };
    </script>
    
    <style lang="scss" scoped></style>
    

    登录页(Login.vue):

    <template>
      <div>
        <h3>用户登录</h3>
        <hr />
        <div>
          <input v-model="username" />
        </div>
        <div>
          <input v-model="password" />
        </div>
        <div>
          <button @click="login">进入系统</button>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          username: 'admin',
          password: 'admin'
        }
      },
      methods: {
        login() {
          if (this.username === 'admin') {
            localStorage.setItem('token','fewfewlfewlkfewlkfelfew')
            // this.$router.replace('/admin/dashboard')
            this.$router.replace('/admin')
            // this.$router.replace('/home')
          } else {
            alert('登录失败')
          }
        }
      }
    }
    </script>
    
    <style lang="scss" scoped></style>
    

    后台管理页(admin.vue):

    <template>
      <div>
        <h3>后台管理</h3>
        <hr />
        <menus />
        <!-- 嵌套路由,一定要在父路由中添加对应的 挂载点 -->
        <router-view />
      </div>
    </template>
    
    <script>
    import menu from './ui/menu.vue'
    export default {
      components: {
        menus: menu
      },
      // 在嵌套路由的父级中书写业务代码,可以实现登录跳转
      // 如果登录不成功就无法获取token值,此时重定向到登录页面
      created() {
        if (!localStorage.getItem('token')) {
          this.$router.replace('/login')
        }
      }
    }
    </script>
    
    <style lang="scss" scoped></style>
    

    在这里插入图片描述

7. 动态路由匹配

描述:

所谓动态路由就是路由规则中有部分规则动态变化的,不是固定的值,需要去匹配取出数据(即路由参数)。

比如我们有这样一个场景,在页面中有新闻 1 、新闻 2 、新闻 3 三个选项,点击不同的选项会显示不同的新闻详情页,那么我们要如何实现这个功能呢?

我们可以通过?在地址栏传入 id 值,通过参数控制跳转。但是这种方式不够安全,有可能会暴露后台数据。而且当地址栏中出现?时,浏览器会判定当前页面为动态网站,动态网站在 SEO 搜索引擎中权重比静态网站要低,不利于 SEO 优化。

所以,当我们需要一个唯一标识来控制显示哪个页面时,就需要用到动态路由匹配。

动态路由匹配安全性更高,且会被浏览器判定为静态页,在搜索引擎中排名较高。

语法:

// 传递参数id
var router = new VueRouter({
    // routes是路由规则数组 
    routes: [
        { path: '/user/:id', component: User },
    ]
})

// 组件中获取id值
const User = {
    template: '<div>User ID is {{$route.params.id}}</div>'
}

使用:

路由配置(index.js):

// 1.引入相关库文件
import Vue from 'vue'
import VueRouter from 'vue-router'

// 3.定义渲染的组件  === 视图组件 容器组件
import News from '@/views/News'
import Detail from '@/views/Detail'

// 2.以插件的方式添加,将VueRouter引入到Vue类中
Vue.use(VueRouter)

// 配置路由表
const routes = [
    {
        path: '/news',
        component: News
    },
    // 动态路由参数,一定要先定义,后使用
    {
        // :名称 定义动态路由参数的方式,可以定义N个  /:a/:b/:c
        // path: '/detail/:nid',
        // 可选路由参数,即没有参数也可以访问到详情页面
        path: '/detail/:nid?',
        component: Detail
    }
]

// 4.实例化路由对象及配置路由表
const router = new VueRouter({
    // 路由模式
    mode: 'history',
    // 路由规则表
    routes
})

// 5.导出
export default router

新闻页面(index.vue):

<template>
  <div>
    <li>
      <!-- 这里也可以传入 query 数据 -->
      <router-link to="/detail/1?name=abc">新闻1</router-link>
    </li>
    <li>
      <router-link to="/detail/2">新闻2</router-link>
    </li>
    <li>
      <router-link to="/detail/3">新闻3</router-link>
    </li>
  </div>
</template>

<script>
export default {}
</script>

<style lang="scss" scoped></style>

新闻详情页(index.vue):

<template>
  <div>
    <h3>详情页面 --- {{ $route.params.nid || 0 }} == {{ nid }}</h3>
  </div>
</template>

<script>
export default {
  computed: {
    nid() {
      // 返回动态路由参数
      return this.$route.params.nid || 0
    }
  },
  mounted() {
    // 获取动态路由传过来的 query 数据
    // 注意:这里获取的数据是个对象,对象的属性值是字符串,如果要参与数值运算需要先转化为数值
    console.log(this.$route.query)
  },
}
</script>

<style lang="scss" scoped></style>

在这里插入图片描述

注意:

  • 如果不使用动态路由参数,而使用 query 的方式(即在地址栏中传入?)向地址栏中传入数据:

    优点:不需要提前定义,只要传入字符串即可,操作方便。

    缺点:不利于 SEO 优化;地址栏不优雅;暴露了敏感字段,安全性低。

  • 如果使用动态路由参数,使用 params 的方式匹配动态路由:

    优点:地址栏很优雅,没有问号;搜索引擎权重高;隐藏了字段名,安全性更高。

    缺点:必须要先定义后使用,如果是对于很多项不确定的参数使用这种方式的话,定义起来会变得很麻烦。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值