Vue-Router
首先了解两个概念:单页应用和路由。
安装、配置 vue-router
安装
对应vue工程,我们使用命令行进行安装:
npm install vue-router
// 或者
yarn add vue-router
配置
这些配置可以写在src/main.js 文件中,不过当配置过多时,建议写在src/router/indes.js 中。
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
import Foo from "./views/Foo.vue";
import Bar from "./views/Bar.vue";
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
const router = new VueRouter({
routes
})
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="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<router-view> <!-- 这里面会显示main.js中配置的组件 --!> </router-view>
</div>
</template>
导入组件的写法
导入组件除了上面import 之外,还可以直接在router 中书写,同时还可以为路由命名:
const routes = [
{ path: '/foo',
name: 'fooName',
component: () => import('./views/Foo.vue')
}
];
通过命名进行跳转:
<router-link :to="{name: 'fooName'}">Go to Foo</router-link>
路由布局管理(嵌套)
- 在组件中配合路由使用
<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>
<router-view></router-view>
</div>
</template>
Album.vue中:
<template>
<div id="album">
<div class="banner">banner</div>
<router-view></router-view>
</div>
</template>
- 定义嵌套路由
const routes = [
{
path: '/album',
component: Album,
children: [
{ path: 'list', component: List },
{ path: 'add', component: Add }
]
}
];
- 需要注意的是:如果希望用路径
"/album/list" 对应在 Album.vue 中渲染出 list,那么子路由中的 path 有两种写法:path: 'list' 或者path: '/album/list' ,但是/list 这样的写法是错误的,因为以反斜杠开头的嵌套路径会被当成根路径,那么 List.vue 会被直接渲染到 App.vue 中的<router-view> 。 - 空的子路由:基于上面的路由配置,如果想在路径为
/album 时仍想在功能渲染些什么,则可以使用空的子路由:
const routes = [
{
path: '/album',
component: Album,
children: [
{ path: '', component: Empty },
{ path: 'list', component: List },
{ path: 'add', component: Add }
]
}
];
动态路由
动态路由
动态路由即符合某模式的多个路径映射到同一个组件,具体写法为:
import User from "./views/User.vue";
const routes = [
{ 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
页面跳转(router.push)
一、router.push 的参数是字符串路径时
router.push('user')
router.push('/user')
二、router.push 的参数为描述地址的对象
router.push({ path: 'home' })
router.push({ name: 'user', params: { userId: '123' }})
router.push({ path: 'register', query: { plan: 'private' }})
如果使用 path 进行页面跳转时,写 params 进行传参时会被忽略:
router.push({ path: 'user', params: { userId: '123' }})
router.push({ path: 'user/123'})
使用$router 可以获取当前路由的各个参数:
{
name: "user",
meta: {},
path: "/user/123",
hash: "#abc",
query: {name: "userName"},
params: {userId: "123"},
fullPath: "/user/123?name=userName#abc"
}
重定向和别名
别名
顾名思义,即一个路由可以由两个名字来指向它,下面的代码中访问/a 或者是/b 都会渲染A:
const routes: [
{ path: '/a', alias: '/b', component: A }
];
重定向
若路由/a 重定向到/b ,即访问/a 时,url会自动跳转到/b ,然后匹配路由/b :
const routes: [
{ path: '/a', redirect: '/b' }
]
一般情况我们希望把localhost:8080/layout/home 表示为localhost:8080 ,则可以使用上面的别名和重定向来完成:
const routes: [
{
path: '/layout',
alias: '/',
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: {
changeTab(type) {
this.$router.push({ query: { type: type } });
},
updateTab() {
if (!this.$route.query.type) return;
this.tabList.map(menu => {
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() {
const result = await Promise.all([asyncFn1(), asyncFn2()]);
console.log(result);
}
getAsyncFn();
在 vue 中请求数据
使用 async 和 await 请求数据
<script>
export default {
data: function() {
return {
courseList: []
};
},
async mounted() {
await this.queryAllCourse();
},
methods: {
async queryAllCourse() {
const res = await fetch('https://www.fastmock.site/mock/2c5613db3f13a5c02f552c9bb7e6620b/f5/api/queryallcourse');
const myJson = await res.json();
this.courseList = myJson.data;
}
}
}
</script>
给 api 传参
<script>
export default {
data: function() {
return {
course: []
};
},
async mounted() {
await this.getCourse();
},
methods: {
async getCourse() {
const courseId = this.$route.params.courseId
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>
|