Vue.js 2.x笔记:路由Vue Router(6)
1. Vue Router简介与安装
1.1 Vue Router简介
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,构建单页面应用。
Vue Router支持3种路由模式:
◊ hash:使用URL hash值作为路由,HTML5 History API出现之前,前端路由都通过hash来实现。hash实现需要在URL中加上#,Web服务不会解析hash,自动忽略#后面的内容,JavaScript通过window.location.hash读取解析。
◊ history:依赖HTML5 History API和服务器配置
◊ abstract:支持所有JavaScript运行环境,如node服务器端。如果发现没有浏览器的API,路由就会强制进入该模式。
vue-router提供两个指令标签组件来处理这个导航与自动渲染逻辑:
◊ <router-view>:渲染路径匹配到的组件视图
◊ <router-link>:支持用户在具有路由功能的应用中导航
1.2 Vue Router安装
Vue Router官方网址:https://github.com/vuejs/vue-router
Vue Router文档教程:https://router.vuejs.org/zh/
npm安装VueRouter:
npm install vue-router
2. 起步示例
2.1 单个html页面中使用
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>libing.vue</title> <script src="node_modules/vue/dist/vue.min.js"></script> <script src="node_modules/vue-router/dist/vue-router.min.js"></script> </head> <body> <div id="app"> <ul> <li> <router-link to="/home">Home</router-link> </li> <li> <router-link to="/about">About</router-link> </li> </ul> <router-view></router-view> </div> <template id="home"> <div>Home</div> </template> <template id="about"> <div>About</div> </template> <script> var home = Vue.extend({ template: "#home" }); var about = Vue.extend({ template: "#about" }); const routes = [{ path: '/home', component: home },{ path: '/about', component: about } ]; const router = new VueRouter({ routes: routes }); const app = new Vue({ router }).$mount('#app'); </script> </body> </html>
2.2 vue-cli中模块化使用
(1)创建基于vue-cli项目
$ vue init webpack libing.vue
(2)/src/views中新建Home.vue及About.vue
<template> <div>{{ title }}</div> </template> <script> export default { data: function() { return { title: "主页" }; } }; </script>
<template> <div>{{ title }}</div> </template> <script> export default { data: function() { return { title: "关于" }; } }; </script>
(3)/src/route/index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/views/Home' import About from '@/views/About' Vue.use(Router) export default new Router({ routes: [{ path: '/', name: 'home', component: Home }, { path: '/home', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ] })
(4)/src/App.vue
<template> <div id="app"> <ul> <li> <router-link to="/home">Home</router-link> </li> <li> <router-link to="/about">About</router-link> </li> </ul> <router-view/> </div> </template> <script> export default { name: "App" }; </script>
在router-link通过名称引用路由:向to属性传入一个对象显式的声明路由的名称。
<router-link :to="{ name: 'home' }">Home</router-link>
注:在/src/route/index.js中配置路由路径时,创建Router 对象new Router({}),如果不配置 mode,就会使用默认的 hash 模式,该模式下会将路径格式化为 #! 开头。
设置 mode: "history"
将使用 HTML5 history 模式,该模式下没有 # 前缀,而且可以使用 pushState 和 replaceState 来管理记录。
import Vue from 'vue' import Router from 'vue-router' import Home from '@/views/Home' import About from '@/views/About' Vue.use(Router) export default new Router({ mode: 'history', routes: [{ path: '/', name: 'home', component: Home }, { path: '/home', name: 'home', component: Home }, { path: '/about', name: 'about', component: About } ] })
3. 动态路由匹配
在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) ,动态部分 以 : 开头。
/src/router/index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/views/Home' import About from '@/views/About' import User from '@/views/User' Vue.use(Router) export default new Router({ mode: 'history', routes: [{ path: '/', component: Home }, { path: '/home', component: Home }, { path: '/about', component: About }, { // 动态路径参数 以冒号开头 path: '/user/:id', component: User } ] })
User.vue:
<template> <div>User ID:{{ $route.params.id }}</div> </template>
<template> <div>User ID:{{ id }}</div> </template> <script> export default { data() { return { id: this.$route.params.id }; } }; </script>
App.vue:
<template> <div id="app"> <ul> <li> <router-link to="/home">Home</router-link> </li> <li> <router-link to="/about">About</router-link> </li> <li> <router-link to="/user/1">User ID:1</router-link> </li> <li> <router-link to="/user/2">User ID:2</router-link> </li> </ul> <router-view/> </div> </template> <script> export default { name: "App" }; </script>
在User.vue中直接通过 {{ $route.params.id }} 获取路由中路径参数值。
当整个vue-router 注入到根实例后,在组件的内部,可以通过this.$route 来获取到 router 实例。
$route中params 属性来获得动态部分,params 属性是一个对象。
属性名是路径中定义的动态部分 id, 属性值是router-link中to 属性中的动态部分。
在<router-link>中加入一个params的属性来指定具体的参数值。
<router-link :to="{ name: 'user', params:{ id: 1 }}">UserID:1</router-link>
4. 嵌套路由
实际应用界面,通常由多层嵌套的组件组合而成。
vue-router配置嵌套路示例:
App.vue
<template> <div id="app"> <ul> <li> <router-link to="/home">Home</router-link> </li> <li> <router-link :to="{ name: 'about' }">About</router-link> </li> <li> <router-link :to="{ name: 'user', params:{ id: 1 }}">UserID:1</router-link> </li> <li> <router-link to="/user/2">UserID:2</router-link> </li> </ul> <router-view/> </div> </template> <script> export default { name: "App" }; </script>
这里的<router-view>是最顶层的出口,渲染最高级路由匹配到的组件。
一个被渲染组件同样可以包含自己的嵌套 <router-view>。
User.vue
<template> <div> <h2>User ID:{{ $route.params.id }}</h2> <router-view></router-view> </div> </template> <script> export default {}; </script>
要在嵌套的出口中渲染组件,需要在 VueRouter 的参数中使用 children 配置:
index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/views/Home' import About from '@/views/About' import User from '@/views/User' import UserProfile from '@/views/UserProfile' Vue.use(Router) export default new Router({ mode: 'history', routes: [{ path: '/', name: 'home', component: Home }, { path: '/home', name: 'home', component: Home }, { path: '/about', name: 'about', component: About }, { // 动态路径参数 以冒号开头 path: '/user/:id', name: 'user', component: User, children: [{ // 当 /user/:id/profile 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: 'profile', name: 'profile', component: UserProfile }] } ] })
UserProfile.vue
<template> <div>User Profile</div> </template> <script> export default {}; </script>
访问嵌套路由方式:http://localhost:8080/user/1/profile
在嵌套路由中访问父级路由参数:
<template> <div>User Profile:{{ $route.params.id }}</div> </template> <script> export default {}; </script>
当访问 /user/1 时,提供一个 空的子路由。
{ // 动态路径参数 以冒号开头 path: '/user/:id', name: 'user', component: User, children: [{ // 当 /user/:id 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: '', component: UserProfile }, { // 当 /user/:id/profile 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: 'profile', name: 'profile', component: UserProfile }] }
5. 命名视图
若要同级展示多个视图(非嵌套),使用命名视图。
如果router-view没有设置名字,则默认为 default。
<router-view name="main"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。使用 components 配置。
<router-view name="header"></router-view> <router-view name="slidebar"></router-view> <router-view name="main"></router-view> <router-view name="footer"></router-view>
Route配置:
export default new Router({ routes: [{ path: '/', name: 'home', components: { default: Home, header: Header, slidebar: SlideBar, footer: Footer } } ] })
命名嵌套视图:
<template> <div> <h2>User ID:{{ $route.params.id }}</h2> <router-view></router-view> <router-view name="defined"></router-view> </div> </template> <script> export default {}; </script>
export default new Router({ routes: [{ // 动态路径参数 以冒号开头 path: '/user/:id', name: 'user', component: User, children: [{ // 当 /user/:id 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: '', component: UserProfile }, { // 当 /user/:id/profile 匹配成功, // UserProfile 会被渲染在 User 的 <router-view> 中 path: 'profile', name: 'profile', components: { default: UserProfile, defined: UserDefinedProfile } }] } ] })
6. 编程式导航
除了使用 <router-link> 创建 a 标签来定义导航链接,还可以借助 router 的实例方法,通过编写代码来实现。
<template> <div> <input type="button" value="跳转" @click="handleRedirect" /> </div> </template> <script> export default { methods: { handleRedirect() { this.$router.push({ path: "/" }); this.$router.push({ name: 'about'}) this.$router.push({ name: 'user', params: { id: 1 }}) } } }; </script>
7. 导航守卫
7.1 全局前置守卫
使用 router.beforeEach 注册一个全局前置守卫:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
示例:
import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' Vue.use(VueRouter) const routes = [{ path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: () => import('../views/About.vue') } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) // 导航守卫 // 使用 router.beforeEach 注册一个全局前置守卫,判断用户是否登陆。 router.beforeEach((to, from, next) => { if (to.path === '/login') { next(); } else { let token = localStorage.getItem('Token'); if (token === 'null' || token === '') { next('/login'); } else { next(); } } }) export default router