路由
安装:npm i vue-router -S,
推荐使用 vue add router 添加组件(记得提前把代码提交到 git)
在 main,js 中
import Vue from ‘vue’
import VueRouter from ‘vue-router’
Vue.use(VueRouter)
vue-router的基本使用
// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 2.模块化机制 使用 Router
Vue.use(router)
// 3.创建路由器对象
export default new VueRouter({
routes:[
{
path:'/',
name:'home',
component:Home
},
{
path:'/about',
name:'about',
component:About
},
{
path:'/user:id',
name:'user',
component:()=>import('@/views/User')
},
{
path:'*',
component:()=>import('@/views/404')
},
]
})
命名路由
const routes = [
{
path: '/',
name: 'Home', // 对路由命名
component: Home
}
]
<template> <div id="nav"> // :to="{name:'Home'}" 使用命名路由 <router-link :to="{name:'Home'}">Home</router-link> | <router-link :to="{name:'About'}">About</router-link> | </div> <router-view/> </template>
动态路由匹配和路由组件复用
路由 监听、导航守卫
import User from '@/views/User.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
// 准备重用的路由
{
path:'/user',
name:'User',
component:User
}
]
<template> <div id="app"> <!-- :to="{params:{id:2}} params 是对路由的重用设置 --> <div id="nav"> <router-link :to="{name:'Home'}">Home</router-link> | <router-link :to="{name:'User',params:{id:1}}">User_1</router-link> | <router-link :to="{name:'User',params:{id:2}}">User_2</router-link> </div> <router-view/> </div> </template>
<template> <div> 我是用户界面{{ $route.params.id }} </div> </template> <script> export default { // 路由组件会复用的情况 // 当路由参数变化时,/user/1 切换到 /user/2 时,原来的组件实例会被复用 // 因为两个路由渲染了同个组件,复用高效 // created(){ // console.log(this.$route.params.id) // }, // 监听 // 相应路由参数变化 watch:{ $route:function(to){ console.log(to.params.id) // 发起 ajax 请求后端接口数据 数据驱动视图 } }, // 导航守卫 // beforeRouteUpdate(to,form,next){ // console.log(to.params.id) // // 放行,一定要调用 next,不然会柱塞整个路由 // next() // } } </script> <style> </style>
404路由和路由匹配优先级
404 的路由要放到最下面,不然影响正常使用
export default new VueRouter({
routes:[
{
path:'/user:id',
name:'user',
component:()=>import('@/views/User')
},
{
// 404 路由
path:'*',
component:()=>import('@/views/404')
},
]
})
同一个路径可以匹配多个路由,匹配的优先级按照路由的定义顺序
谁先定义,谁的优先级高
export default new VueRouter({
routes:[
// 同一个路径可以匹配多个路由,匹配的优先级按照路由的定义顺序
// 谁先定义,谁的优先级高
// {
// path:'/about',
// name:'about',
// component:()=>import('@/views/User')
// },
{
path:'/about',
name:'about',
component:About
},
]
})
路由查询参数
history 模式,干净的网页地址,没有 #
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/',
name:'home',
component:Home
},
{
path:'/page',
name:'page',
component:()=>import('@/views/Page')
},
]
})
<template> <div id="app"> <div id="nav"> <router-link :to="{name:'user',params:{id:2}}">User_2</router-link> | <router-link :to="{name:'page',query:{id:2,foo:'title'}}">Page</router-link> </div> <router-view/> </div> </template>
<template> <div> <h3>这是一个 Page 界面</h3> </div> </template> <script> export default { created(){ const {id,foo} = this.$route.query console.log(id,foo) // 拿到这些信息就可以与后端进行交互了 } } </script> <style> </style>
路由重定向和别名
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/',
// 重定向
// redirect:'home'
redirect:{name:'home'}
},
{
path:'/home',
name:'home',
component:Home,
// 别名
alias:'/hhh'
},
{
path:'/about',
name:'about',
component:About
},
]
})
路由组件传值
// 3.创建路由器对象
export default new VueRouter({
{
path:'/user:id',
name:'user',
component:()=>import('@/views/User'),
// 路由组件传值
// 方法一
// props:true
// 方法二
props:(route)=>({
id:route.params.id,
title:route.query.title,
})
},
]
})
<template> <div> <h2>这个是 User {{ $route.params.id }}</h2> <h2>使用 props 传值 {{ id }} --- {{ title }}</h2> </div> </template> <script> export default { props:['id','title'], } </script> <style> </style>
如何使用编程式导航
<template> <div> <button @click="goHome">界面跳转</button> <button @click="goBack">后退</button> </div> </template> <script> export default { methods:{ goBack(){ // 正数 前进 0 刷新界面 负数 后退 this.$router.go(-1) }, goHome(){ // 编程时导航 // 方法一 // this.$router.push('/') // 方法二 this.$router.push({ path:'/' }) // 方法三 // this.$router.push({ // name:'user', // params:{id:2} // }) // 方法四 // this.$router.push({ // path:'/reg', // query:{plan:'123'} // }) } } } </script> <style> </style>
嵌套路由的使用
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/user:id',
name:'user',
component:()=>import('@/views/User'),
// 路由组件传值
// 方法一
// props:true
// 方法二
props:(route)=>({
id:route.params.id,
title:route.query.title,
}),
children:[
{
path:'App1',
component:()=>import('@/views/App1')
},
{
path:'App2',
component:()=>import('@/views/App2')
},
]
},
]
})
<template> <div id="app"> <div id="nav"> <!-- 声明式跳转 --> <router-link :to="{name:'user',params:{id:1}}">User_1</router-link> | <router-link :to="{name:'user',params:{id:2}}">User_2</router-link> | <!-- 路由嵌套 --> <router-link to='/user1/App1'>user_1/App1</router-link> | <router-link to='/user2/App2'>user_2/App2</router-link> | </div> <router-view/> </div> </template>
<template> <div> <h2>这个是 User {{ $route.params.id }}</h2> <!-- 子路由的文件出口 --> <router-view></router-view> </div> </template>
命名视图的使用
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/about',
name:'about',
// component:About
// 设置命名视图
components:{
default:About, // 默认的名字
right:()=>import('@/views/right'),
left:()=>import('@/views/left'),
}
},
]
})
<template> <div id="app"> <!-- 渲染 Home 的 --> <router-view/> <router-view name='right' class="right"></router-view> <router-view name='left' class="left"></router-view> </div> </template>
使用全局守卫做登录操作
// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 2.模块化机制 使用 Router
Vue.use(router)
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/note',
name:'note',
component:()=>import('@/views/Note')
},
{
path:'/login',
name:'login',
component:()=>import('../views/Login')
},
{
path:'*',
component:()=>import('@/views/404')
},
]
})
<template> <div id="app"> <div id="nav"> <!-- 声明式跳转 --> <router-link :to="{name:'home'}">Home</router-link> | <router-link :to="{name:'about'}">About</router-link> | <router-link :to="{name:'note'}">我的笔记</router-link> | </div> </div> </template>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
// 全局守卫
router.beforeEach((to,from,next)=>{
// 判断用户是否访问了 note
if(to.path === '/note'){
const user = JSON.parse(localStorage.getItem('user'))
if (user) {
// 用户已登录
next()
}else{
// 用户没有登录 跳转到登录界面
next('/login')
}
}
next()
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
<template> <div> <h2>登录界面</h2> 账号:<input type="text" v-model="user"> 密码:<input type="password" v-model="pawd"> <input type="button" value='登录' @click="login"> </div> </template> <script> export default { data(){ return{ user:'', pawd:'' } }, methods:{ login(){ // 1.获取账号密码 // 2.模拟后端交互 setTimeout(() => { let data = { user:this.user } // 保存用户名到本地 localStorage.setItem('user',JSON.stringify(data)); // 跳转到 note this.$router.push('/note') }, 1000); } } } </script> <style> </style>
组件内部的守卫的应用
// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 2.模块化机制 使用 Router
Vue.use(router)
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/edit',
name:'edit',
component:()=>import('../views/Edit')
},
{
path:'*',
component:()=>import('@/views/404')
},
]
})
<template> <div id="app"> <div id="nav"> <router-link :to="{name:'edit'}">编辑</router-link> | </div> </div> </template>
<template> <div> <textarea v-model="edit" id="" cols="30" rows="10"></textarea> <button @click='save'>保存</button> <ul> <li v-for="(item,index) in list" :key="index"> <h4>{{ item.title }}</h4> </li> </ul> </div> </template> <script> export default { data(){ return{ edit:'', list:[] } }, methods:{ save(){ this.list.push({ title:this.edit }) // 清空文本框 this.edit = ''; } }, // beforeRouteUpdate(to,from,next){ // // 组件重用时 这个方法才起作用 // next(); // }, beforeRouteLeave(to,from,next){ if (this.edit) { alert('请保存后在离开') next(false) }else{ next() } } } </script> <style> </style>
路由meta元信息实现权限控制
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/page',
name:'page',
component:()=>import('@/views/Page'),
meta:{
// 加入到黑名单
requireAuth:true
}
},
{
path:'/edit',
name:'edit',
component:()=>import('../views/Edit'),
meta:{
// 加入到黑名单
requireAuth:true
}
},
{
path:'*',
component:()=>import('@/views/404')
},
]
})
<template> <div> <h2>登录界面</h2> 账号:<input type="text" v-model="user"> 密码:<input type="password" v-model="pawd"> <input type="button" value='登录' @click="login"> </div> </template> <script> export default { data(){ return{ user:'', pawd:'' } }, methods:{ login(){ // 1.获取账号密码 // 2.模拟后端交互 setTimeout(() => { let data = { user:this.user } // 保存用户名到本地 localStorage.setItem('user',JSON.stringify(data)); // 跳转到 note this.$router.push({ path:this.$route.query.redirect }) }, 1000); } } } </script> <style> </style>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
// 全局守卫
router.beforeEach((to,from,next)=>{
if(to.matched.some(record=>record.meta.requireAuth)){
// 需要权限 在黑名单中
if (!localStorage.getItem('user')) {
next({
path:'/login',
query:{
redirect:to.fullPath
}
})
}else{
next();
}
}
// 在白名单中
next();
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
路由组件内在什么时机获取数据
module.exports = {
devServer:{
before:(app,serve)=>{
app.get('/api/post',(req,res)=>{
res.json({
title:'vue-router 的数据获取',
body:'在导航完成之后获取数据'
})
})
}
}
}
// 1.导入
import Vue from 'vue'
import router from 'vue-router'
import VueRouter from 'vue-router'
// 2.模块化机制 使用 Router
Vue.use(router)
// 3.创建路由器对象
export default new VueRouter({
mode:'history', // history 模式,干净的网页地址
routes:[
{
path:'/post',
name:'post',
component:()=>import('../views/Post')
},
{
path:'*',
component:()=>import('@/views/404')
},
]
})
<template> <div id="app"> <div id="nav"> <!-- 声明式跳转 --> <router-link :to="{name:'home'}">Home</router-link> | <router-link :to="{name:'about'}">About</router-link> | <router-link :to="{name:'note'}">我的笔记</router-link> | <router-link :to="{name:'edit'}">编辑</router-link> | <router-link :to="{name:'post'}">Post</router-link> | </div> </div> </template>
<template> <div class="post"> <div v-if="loading" class="loading">Loading...</div> <div v-if="error" class="error">{{ error }}</div> <div v-if="post"> <h2>标题:{{ post.title }}</h2> <h2>内容:{{ post.body }}</h2> </div> </div> </template> <script> export default { data(){ return{ post:null, error:null, loading:false } }, // 导航完成之后获取数据 created(){ console.log(this.$https) this.getPostData() }, watch:{ $route:"getPostData" }, methods:{ async getPostData(){ try { this.loading = true const {data} = await this.$https.get('/api/post') this.loading = false this.post = data; } catch (error) { console.log(error); this.error = error.toString() } } } } </script> <style> </style>