使用vue-cli安装不需要另外安装路由,只需要在安装时候选择Manually select features,然后选到router按下空格就行
路由配置
- Router
- Views
//main.js
import router from "./router"
new Vue({
router,
render: h => h(App)
}).$mount('#app')
初始化路由
在路由模块的入口文件index.js配合router
//引入vue
import Vue from 'vue';
//引入router
import VueRouter from 'vue-router'
//引入组件
import Home from "../xxx/Home.vue";
import About from "../xxx/About.vue"
//全局配置路由
Vue.use(VueRouter)
//集成路由
const routes = [
{
//路径
path:"/",
//路由名称
name:"home",
//路由加载的组件
component:Home
},
{
path:"/about",
name:"about",
component:About,
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
嵌套路由
嵌套路由用到了children属性,实现嵌套
//引入vue
import Vue from 'vue';
//引入router
import VueRouter from 'vue-router'
//引入组件
import Home from "../xxx/Home.vue";
import Hot from "../views/Hot.vue";
//全局配置路由
Vue.use(VueRouter)
//集成路由
const routes = [
{
//路径
path:"/",
//路由名称
name:"home",
//路由加载的组件
component:Home,
//嵌套路由
children:[
{
path: "/hot",
name: "hot",
component: Hot
}
]
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
编程式导航
- 在vue实力内部,你可以通过 r o u t e r 访 问 路 由 实 例 , 因 此 你 可 以 调 用 t h i s . router访问路由实例,因此你可以调用this. router访问路由实例,因此你可以调用this.router.push跳转,这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
- this.$router.push有两种跳转方式,一个是path+query,另一个是name+params
path+query
this.$router.push({
path:'/hello',
query:{
name:'word',
age:'11'
}
})
name+params
this.$router.push({
name:'hello',
params:{
name:'word',
age:'11'
}
})
一般推荐使用path+query进行路由传参
- 使用params带参数,需要对应使用name来指明路径,query带参数,则path,name都可以
- params带参数跳转,在跳转后页面再进行跳转或刷新都有可能导致数据丢失,建议使用query带参数
- query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示
- params是路由的一部分,必须要有。query是拼接在url后面的参数,没有也没关系
- params一旦设置在路由,params就是路由的一部分,如果这个路由有params传参,但是在跳转的时候没有传递这个参数,会导致跳转失败或者页面没有内容,比如跳转router1/:id
<router-link :to="{name:'router1',params:{id:staus}}">正确</router-link>
<router-link :to="{name:'router1',params:{id2:staus}}">错误</router-link>
命名视图
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar
(侧导航) 和 main
(主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view
没有设置名字,那么默认为 default
。
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components配置 (带上 s):
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
在这个默认路由下面,
第一个非未命名视图显示Foo组件
第二个name名为a的视图显示Bar组件
name名为b的视图显示Baz组件
下面这个是一个示例
<template>
<div class="hello">
<ul class="nav">
<li><router-link to="/list1">list1</router-link></li>
<li><router-link to="/list2">list2</router-link></li>
<li><router-link to="/list3">list3</router-link></li>
</ul>
<h6>默认视图</h6>
<div class="view">
<router-view></router-view>
</div>
<h6>a视图</h6>
<div class="view">
<router-view name="a"></router-view>
</div>
<h6>b视图</h6>
<div class="view">
<router-view name="b"></router-view>
</div>
</div>
</template>
router配置:
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld,
children:[
{
path:'',
components:{
default:List1,
a:List2,
b:List3
}
},
{
path:'list1',
components:{
default:List1,
a:List2,
b:List3
}
},
{
path:'list2',
components:{
default:List2,
a:List1,
b:List3
}
},
{
path:'list3',
components:{
default:List3,
a:List1,
b:List2
}
}
]
}
]
嵌套命名视图
我们也有可能使用命名视图创建嵌套视图的复杂布局。这时你也需要命名用到的嵌套 router-view
组件
{
path: '/',
// 你也可以在顶级路由就配置命名视图
component: name,
//嵌套路由
children: [{
path: '/emails',
component: UserEmailsSubscriptions
},
{
path: 'profile',
//命名视图
components: {
default: UserProfile,
helper: UserProfilePreview
}
}]
}
重定向
重定向也是通过 routes
配置来完成,下面例子是从 /a
重定向到 /b
:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' }
]
})
//重定向的目标也可以是一个命名的路由
const router = new VueRouter({
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
//甚至是一个方法,动态返回重定向目标:
const router = new VueRouter({
routes: [
{ path: '/a', redirect: to => {
// 方法接收 目标路由 作为参数
// return 重定向的 字符串路径/路径对象
}}
]
})
代码示例:
{ path: '/dynamic-redirect/:id?',
redirect: to => {
const { hash, params, query } = to
if (query.to === 'foo') {
return { path: '/foo', query: null }
}
if (hash === '#baz') {
return { name: 'baz', hash: '' }
}
if (params.id) {
return '/with-params/:id'
} else {
return '/bar'
}
}
}
导航守卫
vue-router
提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
全局前置守卫beforeEach
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之
前一直处于 等待中。
你可以使用 router.beforeEach
注册一个全局前置守卫:
//模拟登录状态
let loginStatus = false
const router = [
{
path: '/',
name: 'Home',
component: Home,
//设置meta前往路由是否需要通过守卫
meta: {
isLogin: false
}
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
meta: {
isLogin: false
}
},
{
path: "/mine",
name: "mine",
component: () => import("../views/Mine.vue"),
meta: {
isLogin: true
}
}
]
路由独享守卫beforeEnter
let loginStatus = false
const routes = [
{
path: "/shoppinglist",
name: "shoppinglist",
component: ShoppingList,
// 设置路由独享守卫
beforeEnter: (to, from, next) => {
// 判断登录状态
if (loginStatus === false) {
next("/login")
} else {
next()
}
}
}
]
组件内守卫beforeRouteLeave
<script>
export default {
// 设置组件内守卫beforeRouteLeave
beforeRouteLeave (to, from, next) {
window.console.log(to)
window.console.log(from)
window.alert("真的要离开吗")
next()
}
}
</script>
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖
next
方法的调用参数。- next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
- next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到
from
路由对应的地址。 - next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向
next
传递任意位置对象,且允许设置诸如replace: true
、name: 'home'
之类的选项以及任何用在router-link
的to
prop 或router.push
中的选项。 - next(error): (2.4.0+) 如果传入
next
的参数是一个Error
实例,则导航会被终止且该错误会被传递给router.onError()
注册过的回调。
**确保要调用 next 方法,否则钩子就不会被 resolved。