“vue-router可以满足我们简单的路由功能,同时也满足高级功能需求”
本文主要讲解在vue框架中如何使用vue-router组件。先上一张思维导图,对本文的讲解内容有个总体的认识。
01
—
定义
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
嵌套的路由/视图表
模块化的、基于组件的路由配置
路由参数、查询、通配符
基于 Vue.js 过渡系统的视图过渡效果
细粒度的导航控制
带有自动激活的 CSS class 的链接
HTML5 历史模式或 hash 模式,在 IE9 中自动降级
自定义的滚动条行为
这里直接引用官方定义标准。
02
—
安装
1、直接下载或者CDN引入
2、NPM
3、构建开发版本
自己从github上拉取源码,然后build出一个vue-router
git clone https://github.com/vuejs/vue-router.git node_modules/vue-routercd node_modules/vue-routernpm installnpm run build
03
—
基础用法
基础用法可以满足简单的功能需求。理论方面就不一一介绍了,参考官方文档讲的比较详细,https://router.vuejs.org/zh/
这里以项目实操的方式讲解下。
继【前端vue系列】初始化一个vue工程 中搭建的vue脚手架工程(工程源码https://github.com/danfengqingyi/vue-study)已经包括了Router功能。脚手架中已经包括的router基础功能只是简单的起步,并没有包括上面思维导图中的基础用法。虽然脚手架中已经帮我们引入好了Router并且有简单的起步功能,但是我们得掌握如何引入Router。下面讲解下引入Router的步骤:
上面是工程目录结构,可以看到router文件夹,这里面的index.js文件就是进行路由定义的。
引入Router的步骤
1、首先是安装,方式也在02部分中说了
2、导入Vue-Router
import Vue from "vue";import VueRouter from "vue-router";Vue.use(VueRouter);
3、定义路由,每个路由应该映射一个组件
import Home from "../views/Home.vue";const routes = [ { path: "/", name: "Home", component: Home }, { path: "/about", name: "About", component: () => import(/* webpackChunkName: "about" */ "../views/About.vue") }];
4、创建router实例,并传入routes配置参数
const router = new VueRouter({ mode: "history", base: process.env.BASE_URL, routes});
5、导出router实例
export default router;
6、通过router配置参数向Vue根实例中注入路由(这里会创建和挂载Vue根实例)
import Vue from "vue";import App from "./App.vue";import router from "./router";import store from "./store";Vue.config.productionTip = false;new Vue({ router, store, render: h => h(App)}).$mount("#app");
7、在根组件中配置路由出口(导航匹配成功的路由映射的组件在路由出口中渲染显示)
一个项目中可能会有多个路由出口,因为常用项目中界面是由嵌套组件组合而成的。
但至少会有一个路由出口,而且这个路由出口通常会放在根组件中。
<template> <div id="app"> <div id="nav"> <router-link to="/">Homerouter-link> | <router-link to="/about">Aboutrouter-link> div> <router-view /> div>template>
8、路由导航
浏览器地址栏中直接输入URL
编程式的导航
编程式的导航有2种方式:
声明式:
编程式:router.push(...)
<router-link to="/">Homerouter-link> |<router-link to="/about">Aboutrouter-link>
上面2个会创建2个标签来定义导航链接,被点击后,会导航到to属性值对应的路由,从而匹配到映射的组件并渲染显示出来。
router.push(...)这个方式的导航有几种写法:
// 字符串router.push('home')// 对象router.push({ path: 'home' })// 命名的路由router.push({ name: 'user', params: { userId: '123' }})// 带查询参数,变成 /register?plan=privaterouter.push({ path: 'register', query: { plan: 'private' }})
至此一个具备基本起步功能的Router已经引入成功了。
在浏览器中输入localhost:8081 会匹配path为"/"路由,所以会加载映射的组件Home
点击About字样 会跳转至 localhost:8081/about 会匹配path为"/about"路由,所以会加载映射的组件About(红框部分就是About视图组件)
实战嵌套路由
实际开发中的应用界面,通常由多层嵌套的组件组合而成的。
比如上面的About组件是视图组件,被渲染在根组件的中,那么About组件同样可以包含路由出口。
新建两个组件Job和Live,配置路由,让他们可以被渲染在About组件的中。
Job.vue文件代码
<template> <div class="about"> <h1>This is an about Job pageh1> div>template>
Live.vue文件代码
<template> <div class="about"> <h1>This is an about Live pageh1> div>template>
嵌套路由配置:(这样很简单地表达这种关系--URL中各段动态路径按某种结构对应到嵌套的各层组件)
import Home from "../views/Home.vue";import Job from "../views/Job.vue";import Live from "../views/Live.vue";const routes = [ { path: "/", name: "Home", component: Home }, { path: "/about", name: "About", component: () => import(/* webpackChunkName: "about" */ "../views/About.vue"), children: [ { path: "job", name: "job", component: Job }, { path: "live", name: "live", component: Live } ] }];
About组件中引入路由出口(About视图组件就会嵌套Job视图组件和Live视图组件):
注,视图组件是被渲染在路由出口中的组件。
<template> <div class="about"> <div id="nav"> <router-link to="/about/job">Jobrouter-link> | <router-link to="/about/live">Liverouter-link> div> <router-view>router-view> div>template>
下面红色框区域就是About视图组件的嵌套视图组件
实战重定向
路由重定向一般用在具有嵌套路径的场景中。
比如下面About视图组件中有一个子路由,如果没有重定向,当在浏览器
http://localhost:8081/about时候,页面有一个区域会不显示任何东西。那是因为About视图组件中有一个路由出口没有匹配到任何子路由,所以显示为空白。
为了避免这个问题,我们会在访问/about 路径时重定向到一个有映射组件的子路由,比如job子路由(加上redirect: "/about/job")
{ path: "/about", name: "About", //这里重定向 redirect: "/about/job" component: () => import(/* webpackChunkName: "about" */ "../views/About.vue"), children: [ { path: "job", name: "job", component: Job }, { path: "live", name: "live", component: Live } ] }
实战路由组件传参
通过路径参数传递
{ path: "/about", name: "About", redirect: "/about/job/1", component: () => import(/* webpackChunkName: "about" */ "../views/About.vue"), children: [ { //通过路由参数给对应组件传递参数 path: "job/:id", name: "job", component: Job }, { path: "live", name: "live", component: Live } ] }
通过push方法传递
this.$router.push({ name: "live", params: { id: "123" } });
组件内获取参数
const params = this.$route.params;const id = params.id;console.log("params", params);console.log("id", id);console.log("route", this.$route);
04
—
高级用法
高级用法可以满足复杂的功能需求。理论方面就不一一介绍了,参考官方文档讲的比较详细,https://router.vuejs.org/zh/
实战全局路由守卫:利用全局路由守卫来检测需要登录的页面进入前是否已是登录状态,如果已登录,则正常进入到跳转页面,否则跳转至登录页面。
这里以项目实操的方式讲解下。
这里我们在项目src目录下新建一个permission.js文件,文件内容为
import router from "./router";router.beforeEach((to, from, next) => { console.log("beforeEach to", to); console.log("beforeEach from", from); console.log("beforeEach next", next); next();});router.beforeResolve((to, from, next) => { console.log("beforeResolve to", to); console.log("beforeResolve from", from); console.log("beforeResolve next", next); next();});router.afterEach((to, from, next) => { console.log("afterEach to", to); console.log("afterEach from", from); console.log("afterEach next", next);});
在main.js中导入permission.js
require("./permission");
这里我们新建一个组件Login.vue
<template> <div> <div class="login_form"> <input type="text" class="qxs-ic_user qxs-icon" placeholder="用户名" v-model="userName" /> <input type="text" class="qxs-ic_password qxs-icon" placeholder="密码" v-model="password" /> <button class="login_btn" @click="login" type="primary" round :loading="isBtnLoading" > 登录 button> div> div>template>
这里我们需要用cookies来登录成功后的token,需要安装js-cookie
npm install js-cookie --save
登录按钮触发后
login() { if (!this.userName) { console.log("请输入用户名"); return; } if (!this.password) { console.log("请输入密码"); return; } //这里假设登录成功,这里应该有一个登录接口,登录成功后才能执行下面两行代码 //setToken中入参值也应该是登录接口返回的token值 setToken("1111111111111111111111111"); this.$router.push({ path: "/" }); }
permission.js 中的路由守卫也要处理一些登录判断的逻辑
import router from "./router";import { getToken } from "./utils/auth.js";import NProgress from "nprogress"; // progress barimport "nprogress/nprogress.css"; // progress bar styleconst whiteList = ["/login"]; // no redirect whitelistNProgress.configure({ showSpinner: true }); // NProgress Configurationrouter.beforeEach((to, from, next) => { console.log("beforeEach to", to); console.log("beforeEach from", from); console.log("beforeEach next", next); const token = getToken(); console.log("token", token); if (token) { next(); } else { if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入 next(); } else { next("/login"); NProgress.done(); } }});router.beforeResolve((to, from, next) => { console.log("beforeResolve to", to); console.log("beforeResolve from", from); console.log("beforeResolve next", next); next();});router.afterEach((to, from, next) => { console.log("afterEach to", to); console.log("afterEach from", from); console.log("afterEach next", next);});
05
—
总结
本文讲解的代码地址: https://github.com/danfengqingyi/vue-study
参考文档:https://router.vuejs.org/zh/
主要实战了项目中路由常见的运用场景:
1、应用界面由多层嵌套组件组合而成
2、组件之间跳转需要传递参数
3、路径跳转成功前需要判断登录状态,若已登录,则继续跳转至目标路径,否则,跳转至登录页面
文档一定要好好看,文档中内容完全理解了,才能在项目中熟练地运用到对应的业务场景中去。如果要进一步了解原理(为什么),建议看看源码。