【Vue-Router(路由)】

Vue-Router

首先了解两个概念:单页应用路由
在这里插入图片描述

安装、配置 vue-router

安装

对应vue工程,我们使用命令行进行安装:

npm install vue-router
// 或者
yarn add vue-router
配置

这些配置可以写在src/main.js文件中,不过当配置过多时,建议写在src/router/indes.js中。

// 0. 导入 Vue 和 VueRouter,要调用 Vue.use(VueRouter)
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

// 1. 定义 (路由) 组件。
// 可以从其他文件 import 进来
import Foo from "./views/Foo.vue";
import Bar from "./views/Bar.vue";

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

在这里插入图片描述

路由的使用

主要的两个标签

<router-link></router-link><router-view><router-view>

<template>
  <div id="app">
    <h1>Hello App!</h1>
    <p>
      <!-- 使用 router-link 组件来导航. -->
      <!-- 通过传入 `to` 属性指定链接. -->
      <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
      <router-link to="/foo">Go to Foo</router-link>
      <router-link to="/bar">Go to Bar</router-link>
    </p>
    
    <!-- 路由出口 -->
    <!-- 路由匹配到的组件将渲染在这里 -->
    <!-- App.vue 中的 <router-view></router-view> 是路由的最高级出口 -->
    <router-view> <!-- 这里面会显示main.js中配置的组件 --!> </router-view>
  </div>
</template>
导入组件的写法

导入组件除了上面import之外,还可以直接在router中书写,同时还可以为路由命名:

const routes = [
  { path: '/foo',
    name: 'fooName',
    component: () => import('./views/Foo.vue')
  }
];

通过命名进行跳转:

<!-- to 的值是一个对象而不是字符串,所以要在 to 前加 : -->
<router-link :to="{name: 'fooName'}">Go to Foo</router-link>
路由布局管理(嵌套)

在这里插入图片描述

  1. 在组件中配合路由使用<router-view>

App.vue中:

<template>
  <div id="app">
    <h1>Hello App!</h1>
    <p>
      <router-link to="/album/list">Go to Album List</router-link>
      |
      <router-link to="/album/add">Go to Album Add</router-link>
    </p>
    <!-- 路由匹配到的组件将渲染在这里 -->
    <!-- 在本例中为 Album.vue 组件 -->
    <router-view></router-view>
  </div>
</template>

Album.vue中:

<template>
  <div id="album">
    <div class="banner">banner</div>
    <!-- 路由匹配到的组件将渲染在这里 -->
    <!-- 在本例中为 List.vue 组件或 Add.vue 组件 -->
    <router-view></router-view>
  </div>
</template>
  1. 定义嵌套路由
// 0. 导入 Album、List、Add 三个组件
const routes = [
  {
    path: '/album',
    component: Album,
    // children 属性可以用来配置下一级路由(子路由)
    children: [
      { path: 'list', component: List },
      { path: 'add', component: Add }
    ]
  }
];
  1. 需要注意的是:如果希望用路径"/album/list"对应在 Album.vue 中渲染出 list,那么子路由中的 path 有两种写法:path: 'list'或者path: '/album/list',但是/list这样的写法是错误的,因为以反斜杠开头的嵌套路径会被当成根路径,那么 List.vue 会被直接渲染到 App.vue 中的<router-view>
  2. 空的子路由:基于上面的路由配置,如果想在路径为/album时仍想在功能渲染些什么,则可以使用空的子路由:
// 0. 导入 Album、List、Add、Empty 三个组件
const routes = [
  {
    path: '/album',
    component: Album,
    // children 属性可以用来配置下一级路由(子路由)
    children: [
      // 空的子路由
      { path: '', component: Empty },
      { path: 'list', component: List },
      { path: 'add', component: Add }
    ]
  }
];

动态路由

动态路由

动态路由即符合某模式的多个路径映射到同一个组件,具体写法为:

import User from "./views/User.vue";

const routes = [
  // id 就是路径参数,前面要加冒号
  { path: '/user/:id', component: User }
]

当URL匹配到路由中的一个路径时,参数id会被设置到this.$router.params中,可以在组件中读取:

<template>
  <div>user id: {{ $route.params.id }}</div>
</template>
捕获404页面

当用户输入的URL不属于我们注册的任何一个路由时,我们常需要用404 NotFound组件渲染,这里我们使用通配符*匹配任意路径:

import NotFound from "./views/NotFound.vue";

const routes = [
  {
    // 会匹配所有路径
    path: '*',
    component: NotFound
  }
]

需要注意的是:使用通配符时应该将其放在路由的最后,因为路由的匹配通常时按照注册顺序进行匹配的,如果path: '*'放在最前面,那么所有的页面都会因为先匹配搭配通配符而都被渲染为404 NotFound组件。

获取匹配到的路径值

当使用一个通配符时,$router.params中会自动添加一个名为pathMatch的参数,它包含了URL通过通配符匹配到的部分,例如:http://localhost:8081/non-existing/file这个网站被匹配到的内容

this.$route.params.pathMatch // '/non-existing/file'

页面跳转(router.push)

一、router.push的参数是字符串路径时

router.push('user')
router.push('/user')

在这里插入图片描述
二、router.push的参数为描述地址的对象

// 0.这种写法和字符串类型的参数一样
router.push({ path: 'home' })

// 1.命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 2.带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

在这里插入图片描述
如果使用 path 进行页面跳转时,写 params 进行传参时会被忽略:

// params 会被忽
router.push({ path: 'user', params: { userId: '123' }})

//应该这样写:
router.push({ path: 'user/123'})

使用$router可以获取当前路由的各个参数:

// $route
{
  // 路由名称
  name: "user",
  meta: {},
  // 路由path
  path: "/user/123",
  // 网页位置指定标识符
  hash: "#abc",
  // window.location.search
  query: {name: "userName"},
  // 路径参数 user/:userId
  params: {userId: "123"},
  fullPath: "/user/123?name=userName#abc"
}

重定向和别名

别名

顾名思义,即一个路由可以由两个名字来指向它,下面的代码中访问/a或者是/b都会渲染A:

const routes: [
  // 定义 alias 属性
  { path: '/a', alias: '/b', component: A }
];
重定向

若路由/a重定向到/b,即访问/a时,url会自动跳转到/b,然后匹配路由/b

const routes: [
  // 定义 redirect 属性,将 /a 重定向到 /b
  { path: '/a', redirect: '/b' }
]

一般情况我们希望把localhost:8080/layout/home表示为localhost:8080,则可以使用上面的别名和重定向来完成:

const routes: [
  {
    path: '/layout',
    // 别名定为 /
    alias: '/',
    // 重定向到 /home
    redirect: '/home',
    component: ()=> import('@/pages/nest/Layout.vue'),
    children: [
      { path: 'home', component: Home },
      { path: 'courseall', component: CourseAll },
      { path: 'coursedetail/:courseId', component: CourseDetail }
    ]
  }
];

监听路由

监听路由即监听$router的变化,需要用到watch,其中的to就是变化后的路由,from就是变化前的路由:

watch: {
  $route(to,from){
    console.log(to, from);
  }
}

为某个标签添加额外的类名:class="{active: tab.active}",即如果 tab.active 的值为真,则为该标签添加类名 active。

<script>
export default {
  watch: {
    $route(to, from) {
      // 路由变化了就执行更新样式的方法
      this.updateTab();
      console.log(to, from);
    }
  },
  methods: {
  	// 为该标签添加点击事件,使用router实例改变路径参数
    changeTab(type) {
      this.$router.push({ query: { type: type } });
    },
    // 更新样式的方法
    updateTab() {
      // 处理特殊情况,即初始状态时没有传入参数则不执行任何操作
      if (!this.$route.query.type) return;
      
      this.tabList.map(menu => {
      	// 当标签的type等于路径参数的type时,active为true
        menu.active = menu.type === this.$route.query.type;
      });
    }
  }
};
</script>

网络请求 async 与 await

在Js中我们使用fetch请求数据并获得一个Promise对象,其特点就是无等待,所以想对返回的数据进行处理时,只能在then平铺回调的方式中进行处理:

fetch(
  'https://www.fastmock.site/mock/b73a1b9229212a9a3749e046b1e70285/f4/f4-11-1-1'
)
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });
“异步”async 和 “等待异步”await

异步async用于声明一个异步函数,其返回的结果是一个Promise对象;关键字await用于等待一个异步方法执行的完成,他会阻塞后面的代码,等着Promise对象 resolve*,然后得到 resolve 的结果,作为await表达式的值:

async function asyncFn() {
  return {
    "company": "优课达",
    "slogan": "学的比别人好一点"
  };
}

async function getAsyncFn() {
  const result = await asyncFn();
  console.log(result);
}

getAsyncFn();

需要注意的是:关键字await不能在普通的函数中使用,只能在async声明的函数中使用!想要了解关于Promise更多的信息,请看这个文档

多个请求并发执行 Promise.all
async function asyncFn1() {
  return "优课达";
}

async function asyncFn2() {
  return "学的比别人好一点";
}

async function getAsyncFn() {
  // Promise.all()参数是一个函数数组
  const result = await Promise.all([asyncFn1(), asyncFn2()]);
  console.log(result);
}

getAsyncFn();

在 vue 中请求数据

使用 async 和 await 请求数据
<script>
export default {
  data: function() {
    return {
      courseList: []
    };
  },
  async mounted() {
    // 在生命周期 mounted 中调用获取课程信息的方法
    await this.queryAllCourse();
  },
  methods: {
    // 在 methods 对象中定义一个 async 异步函数
    async queryAllCourse() {
      // 在 fetch 中传入接口地址
      const res = await fetch('https://www.fastmock.site/mock/2c5613db3f13a5c02f552c9bb7e6620b/f5/api/queryallcourse');
      // 将文本体解析为 JSON 格式的promise对象
      const myJson = await res.json();
      // 获取返回数据中的 data 赋值给 courseList
      this.courseList = myJson.data;
    }
  }
}
</script>
给 api 传参
<script>
export default {
  data: function() {
    return {
      course: []
    };
  },
  async mounted() {
    await this.getCourse();
  },
  methods: {
    async getCourse() {
      // 从路径中获取课程 id
      const courseId = this.$route.params.courseId
      // 在接口地址后传入参数 id
      const res = await fetch('https://www.fastmock.site/mock/2c5613db3f13a5c02f552c9bb7e6620b/f5/api/getcourse?id=' + courseId);
      const myJson = await res.json();
      this.course = myJson.data;
    }
  }
}
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

帕特里克_海星

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

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

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

打赏作者

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

抵扣说明:

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

余额充值