第10天:前端路由VueRouter

SPA与前端路由

  • 路由是根据不同的url地址来显示不同的页面或内容的功能,这个概念很早是由后端提出的,即浏览器向不同的地址发送请求,后端返回相应的内容。
  • SPA 指的是一个 web 网站只有唯一的一个 HTML 页面,所有组件的展示与切换都在这唯一的一个页面内完成。此时,不同组件之间的切换需要通过前端路由来实现。
  • 前端路由通常是通过监听URL hash属性值的变化,切换页面,hash 属性是一个 可读可写的字符串 ,该字符串是 URL 的锚部分(从 # 号开始的部分)。

前端路由的工作方式
前端路由,指的是 Hash 地址与组件之间的对应关系。

  • 用户点击了页面上的路由链接
  • 导致了 URL 地址栏中的 Hash 值发生了变化
  • 前端路由监听了到 Hash 地址的变化
  • 前端路由把当前 Hash 地址对应的组件渲染都浏览器中

VueRouter安装与使用

  • Vue路由vue-router是官方的路由插件,能够轻松的管理 SPA 项目中组件的切换。(vue适合开发单页面应用,所有的网页内容通过一个html进行切换,在该html通过不同路由进行不同组件的控制,这个控制通过vue-router完成)
  • Vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。
  • vue-router 目前有 3.x 的版本和 4.x 的版本,vue-router 3.x 只能结合 vue2 进行使用,vue-router 4.x 只能结合 vue3 进行使用。
  • 安装:npm install vue-router@4
    参考官方文档:https://router.vuejs.org/installation.html

vue-router的基本使用步骤

vue-router安装

vue-router 3.x 只能结合 vue2 进行使用
vue-router 4.x 只能结合 vue3 进行使用
vue2安装:

npm install vue-router@3

创建路由组件

在项目中定义 Discover.vue、Friends.vue、My.vue 三个组件,将来要使用 vue-router 来控制它们的
展示与切换:
Discover.vue

<template>
    <div>
        <h1>发现音乐</h1>
    </div>
</template>

Friends.vue

<template>
    <div>
    <h1>关注</h1>
    </div>
</template>

My.vue

<template>
    <div>
    <h1>我的音乐</h1>
    </div>
</template>
    

声明路由链接和占位标签

可以使用 标签来声明路由链接,并使用 标签来声明路由占位符。示例
代码如下:
App.vue

<template>
  <div id="app">
    <!-- 声明路由链接 -->
    <router-link to="/discover">发现音乐</router-link>
    <router-link to="/my">我的音乐</router-link>
    <router-link to="/friends">关注</router-link>
    <!-- 声明路由占位标签 -->
    <router-view></router-view>

  </div>
</template>

创建路由模块

在项目中创建 index.js (src/router/index.js)路由模块,加入以下代码:

import VueRouter from "vue-router";
import Vue from "vue";
import Discover from '../components/Discover.vue'
import Friends from '../components/Friends.vue'
import My from '../components/My.vue'

//将VueRouter设置为Vue的插件
Vue.use(VueRouter)

const router = new VueRouter({
    
    
        // 指定hash属性与组件的对应关系
        routes: [
            {
    
     path: '/discover', component: Discover },
            {
    
     path: '/friends', component: Friends },
            {
    
     path: '/my', component: My },
        ]
    })
    // 导出router对象,其他地方使用
export default router

挂载路由模块

在main.js中导入并挂载router

import Vue from 'vue'
import App from './App.vue'
// 文件名字是index.js可以不写,如果是其他文件名则需要写
import router from './router/index.js'

Vue.config.productionTip = false

new Vue({
    
    
    render: h => h(App),
    // router: router(等价)
    router
}).$mount('#app')

vue-router进阶

路由重定向

首页没有内容时,可以指定其中一个页面作为首页显示内容。
路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面。
通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

const router = new VueRouter({
    
    
        // 指定hash属性与组件的对应关系
        routes: [
            // 当用户访问 / 时,跳转到 /discover
            //原本首页没有内容,添加该重定向后,首页显示Discover组件
            {
    
     path: '/', redirect: '/discover' },
            {
    
     path: '/discover', component: Discover },
            {
    
     path: '/friends', component: Friends },
            {
    
     path: '/my', component: My },
        ]
    })

嵌套路由(子路由)

在 Discover.vue 组件中,声明 toplist和 playlist的子路由链接以及子路由占位符。示例代码如下:
Discover.vue

<template>
    <div>
        <h1>发现音乐</h1>
        <!-- 子路由链接 -->
       <router-link to="/discover/toplist">推荐</router-link>
       <router-link to="/discover/playlist">歌单</router-link>
       <hr>
       <router-view></router-view>

    </div>
</template>

在 src/router/index.js 路由模块中,导入需要的组件,并使用 children 属性声明子路由规则:

const router = new VueRouter({
    
    
        // 指定hash属性与组件的对应关系
        routes: [
            {
    
     path: '/', redirect: '/discover' },
            {
    
    
                path: '/discover',
                component: Discover,
                // 通过children属性,嵌套声明子路由
                children: [
                    {
    
     path: "toplist", component: TopList },
                    {
    
     path: "playlist", component: PlayList },
                ]

            },
            {
    
     path: '/friends', component: Friends },
            {
    
     path: '/my', component: My },
            //嵌套声明子路由另一种方法,若子组件多则不方便
            // {path:'/discover/toplist',component:TopList}
        ]
    })

运行结果:
在这里插入图片描述

动态路由

例如有许多商品,需要查看商品详情页,不可能为每个商品创建商品详情页,因此需要对组件进行重用,使用动态路由。
有如下3个路由链接:
My.vue

<template>
    <div>
    <h1>我的音乐</h1>
    <router-link to="/product/1">商品1</router-link>
    <router-link to="/product/2">商品2</router-link>
    <router-link to="/product/3">商品3</router-link>
    <router-view></router-view>
    </div>
</template>

如果不使用动态路由,路由设置方式:

const router = new VueRouter({
    
    
// 指定hash属性与组件的对应关系
    routes: [
      {
    
     path: '/product/1', component: Product },
      {
    
     path: '/product/2', component: Product },
      {
    
     path: '/product/3', component: Product },
]
})

上述方式复用性非常差。
动态路由指的是:把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。在 vue-router 中使用英文的冒号(:)来定义路由的参数项。示例代码如下:

{
    
     path: '/product/:id',component:Product }

index.js中代码添加如下:
在这里插入图片描述
Product.vue

<template>
    <div>
    <h3>商品</h3>
    </div>
</template>

运行结果:
在这里插入图片描述

动态路由参数传递

※※※方法一
通过动态路由匹配的方式渲染出来的组件中,可以使用 $route.params 对象访问到动态匹配的参数值,比如在商品详情组件的内部,根据id值,请求不同的商品数据。
Product.vue

<template>
    <div>
        <!-- vue内置属性,获取动态的id值 -->
    <h3>商品{
   
   {$route.params.id}}</h3>
    </div>
</template>

※※※方法二
为了简化路由参数的获取形式,vue-router 允许在路由规则中开启 props 传参。示例代码如下:
Product.vue

<template>
    <div>
    <!-- 获取动态的id值 -->
    <h3>商品{
   
   {id}}</h3>
    </div>
</template>
<script>
export default {
      
      
    props:["id"]
}
</script>

index.js
在这里插入图片描述
运行结果:
在这里插入图片描述

导航守卫

编程式导航

在这里插入图片描述
除了使用 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写
代码来实现。
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所
以,当用户点击浏览器后退按钮时,则回到之前的 URL。
当你点击 时,这个方法会在内部调用,所以说,点击 等
同于调用 router.push(…) 。

<template>
    <button @click="gotoProduct(2)">跳转到商品2</button>
</template>
<script>
export default {
      
      
    methods:{
      
      
        gotoProduct: function(id){
      
      
        this.$router.push('/movie/${id}')
        }
    }
}
</script>

导航守卫(路由守卫)

导航守卫可以控制路由的访问权限。全局导航守卫会拦截每个路由规则,从而对每个路由进行访问权限的控制。比如没有登录就想访问订单页是不被允许的。

你可以使用 router.beforeEach 注册一个全局前置守卫(下面是伪代码):
所有路由跳转之前都会调用beforeEach方法,next控制是否允许跳转。

router.beforeEach((to, from, next) => {
    
    
if (to.path === '/main' && !isAuthenticated) {
    
    //如果想去主页但是没有登录,跳转到登录页面
    next('/login')
}
else {
    
    
    next()  //验证通过,放行
}
})
  • to : 即将要进入的目标(到哪里去)
  • from : 当前导航正要离开的路由(从哪里来)
  • 在守卫方法中如果声明了 next 形参,则必须调用 next() 函数,否则不允许用户访问任何一个路
    由!
    • 直接放行:next()
    • 强制其停留在当前页面:next(false)
    • 强制其跳转到登录页面:next(‘/login’)

猜你喜欢

转载自blog.csdn.net/weixin_46443403/article/details/129029964