【12.0】Vue之Router的使用

发布时间 2023-08-07 08:33:24作者: Chimengmeng

【一】Router的介绍

  • Router是一种用于实现页面组件跳转的工具。

    • 在单页面应用中,为了实现页面之间的切换,可以使用Router来进行管理和控制。
  • 提倡单页面应用,需要做页面的跳转----》借助于Router实现页面组件的跳转

【二】Router之简单使用

【1】页面跳转

  • 首先需要编写页面组件;
  • 在路由配置文件(如router/index.js)的routes数组中添加一个路由。

【2】组件中实现页面跳转

  • 可以通过使用router-link标签来实现页面跳转
    • 其中to属性可以是一个地址字符串,也可以是一个对象。
    • to:可以是地址,也可以是对象(标签指令:to)
      • <router-link :to="tag_url">
  • <router-link to="/about"></router-link>

方式二:js控制

  • 在组件的javascript代码中使用this.$router.push()来控制路由跳转
    • this.$router.push('/about')

【3】路由跳转时,可以使用对象

(1)通过对象跳转路由name形式

  • 可以通过传递对象参数的方式来指定跳转到已经在路由中注册过的name

  • <router-link :to="{name:'about'}">

(2)通过对象跳转路由path形式

  • 除了使用name,在to属性中也可以直接指定跳转到的路径

  • <router-link :to="{path:'/about'}">

(3)对象中可以有query属性

  • 跳转时,对象中还可以传递query属性,该属性是一个对象类型,会将其中的key-value对拼接到跳转路径后面
  • console.log(this.$route.query)
  • <router-link to="/about?name=dream&age=19">

(4)在另一个页面中取出地址栏中数据

  • console.log(this.$route.query);

(6)使用带参数的路径

  • 在路由配置中,可以定义带参数的路径,通过在路由配置的path中使用:来定义参数名称。

    {
    	path: '/detail/:pk',
    	name: 'detail',
    	component: DetailView
    },
    
  • 在路由访问时,可以通过this.$route.params.pk来获取路径中的参数。

    • this.$route.params.pk

(7)路由跳转时使用带参数的路径

  • 在进行路由跳转时,也可以使用上述带参数的路径形式

  • this.$router.push({name: 'detail', params: {pk: 999}})

  • <router-link :to="{name:'detail',params:{pk:88}}">

(补充)注意区分$route$router

  • this.$route是Vue.js中的一个内置对象,代表当前路由的相关信息。
    • 它包含了当前页面的路径、参数、查询字符串等信息。
    • 通过this.$route可以获取当前路由对象的各种属性
    • 例如path表示当前路径,params表示传递的参数,query表示查询字符串等。
  • this.$router是Vue.js中用来进行路由导航的对象。
    • 它是通过new VueRouter()创建的实例,代表整个路由对象。
    • 通过this.$router可以进行页面跳转、切换路由等操作。
    • 它提供了一些方法如push()replace()go()等,这些方法可以用于在代码中进行页面跳转或路由切换。
  • this.$route是当前路由对象,用于获取当前页面的路由信息,
  • this.$router是整个路由对象,用于进行页面跳转和路由管理。

(补充)关于this.$router的一些方法

  • this.$router.push(path)
    • 相当于点击路由链接,可以返回到当前路由界面;
  • this.$router.replace(path)
    • 用新路由替换当前路由,不可以返回到当前路由界面;
  • this.$router.back()
    • 请求(返回)上一个记录的路由;
  • this.$router.go(-1)
    • 请求(返回)上一个记录的路由;
  • this.$router.go(1)
    • 请求下一个记录的路由

【三】Router之多级路由

【1】新建一个页面组件(DreamView),配置路由

{
path: '/dream',
name: 'dream',
component: DreamView,
},

【2】在页面中,想再显示页面组件,实现点击切换的效果

<h1>dream页面</h1>
<router-link to="dream01">
    <button>dream-01</button>
</router-link>
<router-link to="dream02">
    <button>dream-02</button>
</router-link>

<router-view>
    # 以后这里变换页面组件,多级路由
</router-view>

【3】新建两个页面组件,Dream01.vue,Dream02.vue,配置路由children

{
    path: '/dream',
        name: 'dream',
            component: DreamView,
                children: [ //通过children配置子级路由
                    {
                        path: 'dream01', //此处一定不要写:/news
                        component: Dream01
                    },
                    {
                        path: 'dream02',//此处一定不要写:/message
                        component: Dream02
                    }
                ]
},

【案例】

  • 多级路由是指在一个父级路由下有多个子级路由的情况。

    • 这样可以让我们更好地组织和管理应用程序的路由。
  • 下面是一个例子来详解Vue中的多级路由:

    • 假设我们有一个电子商务网站,主页面包括商品展示和购物车两个模块。
      • 其中,商品展示页面下有多个分类,每个分类又有多个商品。我们希望在URL中通过路由参数动态切换不同分类和商品。

(1)首先,在Vue实例中创建一个Vue Router实例,并定义路由规则:

import Vue from 'vue'
import VueRouter from 'vue-router'

// 引入组件
import Home from '../views/Home.vue'
import Category from '../views/Category.vue'
import Product from '../views/Product.vue'

Vue.use(VueRouter)

// 定义路由规则
const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/category/:categoryId',
    name: 'category',
    component: Category,
    children: [
      {
        path: 'product/:productId',
        name: 'product',
        component: Product
      }
    ]
  }
]

// 创建路由实例
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

(2)接下来,我们需要在父组件中设置路由出口,以及导航到子级路由:

<!-- Home.vue -->
<template>
  <div>
    <h1>Home</h1>
    <router-link to="/category/electronics">Electronics</router-link>
    <router-link to="/category/books">Books</router-link>
  </div>
</template>

<!-- Category.vue -->
<template>
  <div>
    <h2>{{ $route.params.categoryId }}</h2>
    <router-view></router-view>
  </div>
</template>

<!-- Product.vue -->
<template>
  <div>
    <h3>{{ $route.params.productId }}</h3>
    <!-- 商品相关内容 -->
  </div>
</template>
  • 在上述代码中,父组件Home.vue中通过<router-link>标签定义了两个路由链接到不同的分类页面。
    • 而子组件Category.vue使用了动态路由参数$route.params来获取并显示当前的分类ID,并通过<router-view>标签渲染子级路由Product.vue

(3)最后,我们需要在根组件上添加<router-view>标签将路由组件进行渲染:

<!-- App.vue -->
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>
  • 这样,当我们点击分类链接时,Vue Router会根据URL的路径匹配路由规则,并将对应的组件渲染到<router-view>标签中。
    • URL的路径可以包含动态参数,这样我们就可以根据参数的变化加载不同的子级路由组件。

【四】Router之路由守卫

【介绍】

  • 在Vue Router中,路由守卫是一种机制,用于在导航发生前、发生时和发生后执行一些操作。
    • 通过使用路由守卫,我们可以控制路由的访问权限、实现登录验证、处理异步请求等操作。
  • Vue Router提供了三种类型的路由守卫:
    • 全局守卫、路由独享守卫和组件内守卫。

【案例】

  • 假设我们有一个需要进行登录验证的应用程序,只有在用户已登录的情况下才能访问某些页面。
    • 我们希望在用户访问受保护的页面之前进行登录验证,并在登录成功后才允许访问。

(1)首先,在Vue Router实例中定义路由规则,并添加路由守卫:

import Vue from 'vue'
import VueRouter from 'vue-router'

// 引入组件
import Home from '../views/Home.vue'
import Dashboard from '../views/Dashboard.vue'
import Login from '../views/Login.vue'

Vue.use(VueRouter)

// 定义路由规则
const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/dashboard',
    name: 'dashboard',
    component: Dashboard,
    meta: { requiresAuth: true } // 定义需要登录验证的页面
  },
  {
    path: '/login',
    name: 'login',
    component: Login
  }
]

// 创建路由实例
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

// 全局前置守卫
router.beforeEach((to, from, next) => {
  // 判断是否需要登录验证
  if (to.meta.requiresAuth) {
    // 判断用户是否已登录,这里假设通过判断localStorage中的登录状态来确定
    const isAuthenticated = localStorage.getItem('isAuthenticated')
    if (!isAuthenticated) {
      // 如果未登录,则跳转到登录页面
      next('/login')
    } else {
      // 已登录,允许访问
      next()
    }
  } else {
    next()
  }
})

export default router
  • 上述代码中,我们在路由规则中的"/dashboard"路径下定义了一个元字段meta: { requiresAuth: true }来标识该页面需要登录验证。
    • 然后,在全局前置守卫beforeEach中对每个路由进行拦截和验证。
  • 在全局前置守卫中,我们首先判断将要访问的路由是否需要登录验证。
    • 如果需要验证,则判断用户是否已登录,这里假设通过判断localStorage中的登录状态来确定。
    • 如果用户未登录,则跳转到登录页面;如果用户已登录,则允许访问。

(2)接下来,在登录成功后,我们可以将登录状态存储到localStorage中,并使用router.push()方法跳转到受保护的页面:

// Login.vue
methods: {
  login() {
    // 登录验证逻辑
    // ...

    // 登录成功,将登录状态存储到localStorage中
    localStorage.setItem('isAuthenticated', true)

    // 跳转到受保护的页面
    this.$router.push('/dashboard')
  }
}
  • 这样,当用户访问受保护的页面时,Vue Router会先执行全局前置守卫,进行登录验证。
    • 只有在登录成功后才允许访问。

【五】Router之路由的两种工作模式

路由器的两种工作模式

  • 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。

  • hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器

  • hash模式

    • 地址中永远带着#号,不美观
    • 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
    • 兼容性较好。
  • history模式

    • 地址干净,美观
    • 兼容性和hash模式相比略差
    • 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题
  • Vue中的路由器有两种工作模式:
    • hash模式和history模式。

【1】Hash模式:

  • 对于一个URL来说,hash值是指URL中#号及其后面的内容。
    • 例如,URL为http://example.com/#/home
    • 那么#/home就是hash值。
  • Hash模式的特点是
    • URL中永远带着#号,不会包含在HTTP请求中发送给服务器。
  • 优点:
    • 兼容性较好,支持在不同浏览器和平台上正常运行。
  • 缺点:
    • URL不够美观
    • 如果通过第三方手机APP分享地址,有些严格的APP可能会将带有#号的URL标记为不合法。

【2】History模式:

  • History模式通过利用HTML5的history API
    • 在不刷新页面的情况下改变URL,使得URL更加干净、美观。
  • History模式的特点是
    • URL中不再带有#号,可以直接访问类似于传统URL的路径。
  • 优点:
    • 地址干净、美观,与传统URL一样,更符合用户的习惯。
  • 缺点:
    • 相对于Hash模式,兼容性较差。
    • 特别是在部署上线时,需要服务器的支持来解决刷新页面后可能出现的服务端404错误问题。

【3】示例演示Vue Router中的两种工作模式的切换

import Vue from 'vue'
import VueRouter from 'vue-router'

import Home from '../views/Home.vue'
import About from '../views/About.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
]

const router = new VueRouter({
  // 使用hash模式
  // mode: 'hash',

  // 使用history模式
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router
  • 在上述代码中
    • 我们可以根据需要注释掉其中一种模式,分别测试hash模式和history模式。
  • 如果使用hash模式
    • 可以将mode的值设为'hash'
    • 例如:mode: 'hash'
  • 如果使用history模式
    • 可以将mode的值设为'history'
    • 例如:mode: 'history'
  • 在实际开发中,只需根据具体需求选择一种模式即可
    • 如果要使用history模式,还需要确保在部署应用程序时服务器进行相应的配置。

【补充】localstorage和sessionstorage,和cookie

  • 前端存储数据
    • 登录成功,有token,存本地
      • 京东...
    • 不登陆加购物车
      • 迪卡侬官网
  • 前端可以存数据的位置
    • localstorage:永久存储,除非你删除,关闭浏览器,再打开还会在
    • sessionstorage:只在当前会话生效,关闭浏览器,就没了
    • cookie:有过期时间,到了过期时间,自动删除
<template>
<div class="home">
    <h1>操作localstorage,永久存储</h1>
    <button @click="addLocalstorage">增加</button>
    <button @click="getLocalstorage">查</button>
    <button @click="deleteLocalstorage">删除</button>
    <h1>操作sessiostorage,当前会话,关闭浏览器</h1>
    <button @click="addSessiostorage">增加</button>
    <button @click="getSessiostorage">查</button>
    <button @click="deleteSessiostorage">删除</button>


    <h1>操作cookie,有过期时间</h1>
    <button @click="addCookie">增加</button>
    <button @click="getCookie">查</button>
    <button @click="deleteCookie">删除</button>

    </div>
</template>

<script>

    export default {
        name: 'HomeView',
        methods: {
            addLocalstorage() {
                var userinfo = {name: 'dream', age: 19}
                localStorage.setItem('userinfo', JSON.stringify(userinfo))

            },
            getLocalstorage() {
                var userinfo = localStorage.getItem('userinfo')
                console.log(JSON.parse(userinfo).name)

            },
            deleteLocalstorage() {
                localStorage.clear()
                localStorage.removeItem('userinfo')

            },
            addSessiostorage() {
                var userinfo = {name: '彭于晏', age: 19}
                sessionStorage.setItem('userinfo', JSON.stringify(userinfo))

            },
            getSessiostorage() {
                var userinfo = sessionStorage.getItem('userinfo')
                console.log(JSON.parse(userinfo).name)

            },
            deleteSessiostorage() {
                sessionStorage.clear()
                sessionStorage.removeItem('userinfo')

            },
            addCookie() {
                // 需要借助于第三方  vue-cookies
                // cnpm install -S vue-cookies
                this.$cookies.set('name', '刘亦菲', '300s')

            },
            getCookie() {
                console.log(this.$cookies.get('name'))

            },
            deleteCookie() {
                this.$cookies.remove('name')

            },
        }


    }
</script>

【1】localStorage:

  • localStorage用于在浏览器中永久保存数据,除非手动删除或清除浏览器缓存。
    • 即使关闭浏览器再次打开,数据仍然可以被访问到。
  • 在登录成功后
    • 如果有token需要持久保存,可以将token存储在localStorage中。
  • localStorage提供了setItem(key, value)和getItem(key)等方法来设置和获取数据。
  • 示例代码如下:
// 存储token到localStorage
localStorage.setItem('token', 'your_token_here');

// 从localStorage中获取token
const token = localStorage.getItem('token');

【2】sessionStorage:

  • sessionStorage用于在当前会话中临时保存数据,一旦会话结束(浏览器窗口关闭),数据就会被清除。
  • 当用户未登录但需要加入购物车时,可以使用sessionStorage来存储相关数据。
  • sessionStorage的使用方式与localStorage类似,示例代码如下:
// 存储购物车商品ID到sessionStorage
sessionStorage.setItem('cartItemId', 'your_item_id_here');

// 从sessionStorage中获取购物车商品ID
const cartItemId = sessionStorage.getItem('cartItemId');

【3】cookie:

  • cookie是存储在用户浏览器上的小型文本文件,它具有过期时间。
    • 当过期时间到达时,cookie会被自动删除。
  • 可以使用cookie来实现一些需要在多个页面之间共享的数据。
  • 通过document.cookie属性可以设置和获取cookie值。
  • 示例代码如下:
// 存储一个带过期时间的cookie
document.cookie = 'token=your_token_here; expires=Thu, 1 Jan 2024 12:00:00 UTC; path=/';
  
// 获取cookie
const cookieValue = document.cookie;

【4】小结

  • 需要注意的是,安全性方面,为了避免敏感信息泄露,不建议将用户的敏感数据直接存储在localStorage、sessionStorage或cookie中。
    • 在实际开发中,对于敏感信息,最好使用安全的传输方式(例如HTTPS)进行传输,并在服务器端进行相应的验证和存储。
  • 另外
    • 对于cookie,还需要注意设置合适的域名和路径,以确保cookie的正确读取和写入。
    • 同时,需要注意防止跨站脚本攻击(XSS)和跨站请求伪造攻击(CSRF),对cookie进行适当的安全处理。