把原作者文档放在这里,除了该文档以外的内容,均属于作者自己理解,如有错误敬请指正。
嵌套路由 | Vue Router (vuejs.org)
引入:
#1.创建文件时进行选择
#2.ui界面在运行时依赖中搜索vue-router添加
#3.npm install vue-router
随后在vue的main.js文件中引入:
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
src/router/index.js
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',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = new VueRouter({
mode: 'history',//模式
base: process.env.BASE_URL,//进程配置
routes//
})
export default router
在App.vue中实现简单的路由跳转:
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<!-- 不建议使用 -->
<a href="/about">About</a> |
<router-link to="/me">我的</router-link>
</div>
<!-- 在此处显示路由信息 -->
<router-view/>
</div>
</template>
在组件开发中,我们常常把组件信息放入component,把页面放入view
方法的方式:
goto: function () {
this.$router.push({
path: '/'
})
}
有时候我们需要用到嵌套路由,也就是子路由的形式比如user路由下可能由用户信息增加,用户信息查找,用户信息编辑等组成。
此时访问/me是Me组件,访问/me/weather是Weather组件
{
path: '/me',
name: 'Me',
component: Me,
children: [
{
path: 'weather',
name: 'Weather',
component: Weather
}
]
}
我们需要在一个路由中,想要通过传入数据的不同来显示不同的信息,也就是动态路由。想要做到其实很简单,
我们需要在路径加入动态参数
{
path: '/me',
name: 'Me',
alias: '/my',
props: true,
component: Me,
children: [
{
path: 'weather/:city',
name: 'Weather',
props: true,
component: Weather
}
]
}
如上述代码,:city便是一个动态参数,我们可以通过/me/weather/cityname来实现动态路由,它的值被存放在
this.city = this.$route.params.city
在动态路由中,我们看到接受传参其实是一个很麻烦的事情,$route会使之与其对应路由形成高度耦合
我们在学组件传值时用到了props,此时我们也想那么做:
{
path: '/about/:id',
name: 'About',
// props采用bool值的方式,将route.params 将会被设置为组件属性。
props: true,
}
此时我们传递的参数会在about组件的props属性中
export default {
props: ['id']
}
利用对象的方式传递参数:
代表该对象可以传值到props,其实就是个静态传参
props: { obj: '张三' },
接收:
export default {
props: ['obj'],
mounted(){
console.log(this.obj)
}
}
利用函数的方式传递参数:
{
path: '/about/:obj',
name: 'About',
props: true,
props: (route) => ({
// 把params和query全部传递进来
params: route.params,
query: route.query
}),
},
接收:
export default {
props: ['params', 'query']
}
其实就是通过js代码实现路由跳转和信息传递。
gotopage () {
// 进入指定页面,方式是跳转
// 字符串(路径)
// this.$router.push('me/weather/深圳')
// 对象
// this.$router.push({ path: 'me/weather/深圳' })
// 路由名称方式
// this.$router.push({ name: 'Weather' })
// 路由名称方式传递参数
// this.$router.push({ name: 'Weather', params: { city: '深圳' } })
// 注意路径方式传递参数params会被忽略
// this.$router.push({ path: 'me/weather/深圳', params: { city: '深圳' } })
// 有时候url可能需要参数比如me/weather/深圳?type= 此时需要query
// this.$router.push({ path: 'me/weather/深圳', query: { plan: 'now' } })
// this.$router.push({ name: 'Weather', params: { city: '深圳' }, query: { plan: 'now' } })
},
replacepage () {
// 进入指定页面,方式是替换
// 打个比方,router相当于一个数组[]push是往后添加,replace是替换当前索引处数据
// this.$router.replace('me/weather/深圳')
this.$router.replace({ name: 'Weather', params: { city: '深圳' }, query: { plan: 'now' } })
},
gotopre () {
// 前进几页就写几
this.$router.go(1)
},
gotonext () {
// 后退几页就写负几
this.$router.go(-1)
}
其实路由命名这个我们已经见过了,此处主要是说一下作用:
{
path: '/',
name: 'Home',//命名
components: {
nav: navView,
default: Home
}
}
在进行跳转的时候可以通过名称:
<router-link :to="{ name: 'user'}">User</router-link>
<!-- 编程式路由导航中也有 -->
有时候同级需要展示多个视图时使用
<router-view name="nav"></router-view>//指定名称
<router-view/>//默认视图
js
{
path: '/',
name: 'Home',
components: {
nav: navView,//一个视图
default: Home//默认视图
}
}
打个比方访问/a,实际访问的是/b,显示的也是/b
//简单重定向
{
path: '/ws',
redirect: '/about'
},
//函数判断后重定向
{
path: '/wc',
redirect: (to) => {
if (to.path === '/wc') {
return '/about'
}
}
},
访问/a,实则访问/b,但是显示/a
{
path: '/me',
name: 'Me',
alias: '/my',
props: true,
component: Me,
}
上述例子,访问/me和/my是一样的。
跳转前
// 跳转前
// from是从哪里来,to是跳转到哪里,next是跳不跳转
router.beforeEach((to,from,next)=>{
if(to.path === '/') {
next()
} else {
// 如果要去的地方不是 /home , 就放行
next('/')
}
})
跳转后
用于信息记录
// 跳转后
router.afterEach((to,from,next)=>{
})
有时候我们的有些路由需要这个操作,大部分页面是游客也可以访问的,一部分路由独享守卫就可以通过:
{
path: '/',
name: 'Home',
components: {
nav: navView,
default: Home
},
beforeEnter:(to,from,next)=>{
console.log(1);
}
},
组件内进行操作
//next后才能调用钩子函数
export default {
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
console.log('进入前');
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
console.log('更新前');
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
console.log('离开前');
}
}
给路由一些信息,比如说想跳转该路由是不是需要登录等等
{
path: '/',
name: 'Home',
components: Home,
meta: { requiredLogin: true }
},
路由跳转时做判断:
router.beforeEach((from,to,next)=>{
// 可以做登录判断
let isLogin = true;
if(to.matched.some(record=>record.meta.requiredLogin)){
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next()
}
})
给animate.css打个广告
<transition mode="out-in" name="slider" enter-active-class="animated bounceInRight" leave-active-class="animated bounceOutRight">
<router-view></router-view>
</transition>
动态的
<transition :name="transitionName">
<router-view></router-view>
</transition>
//父组件
watch: {
'$route' (to, from) {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}
比如你看到了一百多行,然后弹了个广告,你关掉回到当前页面想要继续看那么:
const router = new VueRouter({
mode: 'history', // 模式
base: process.env.BASE_URL, // 进程配置
routes, //
scrollBehavior (to, from, savedPosition) {
if(to.path==='/list'){
return savedPosition
}
}
})
路由其实就相当于一个页面所呈现的一部分了,当我们制作一个单页面应用,如果有很多页面一次性加载当然是不好的,最好的方法是懒加载,即第一次使用时加载
即使用的时候再导入:
{
path: '/list',
name: 'List',
component: ()=>import('@/views/List.vue')
}
同时一些常用页面或者是相关联的页面,我们想要让他们一起加载:
这是我们创建项目的时候带的,
/* webpackChunkName: "about" */
这句注释就是一起加载的关键,about相当于是他们的组名称
其实原理就是webpack打包的时候一起打包
{
path: '/about/:obj',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/list',
name: 'List',
component: ()=>import(/* webpackChunkName: "about" */ '@/views/List.vue')
}
redirected
:在导航守卫中调用了 next(newLocation)
重定向到了其他地方。aborted
:在导航守卫中调用了 next(false)
中断了本次导航。cancelled
:在当前导航还没有完成之前又有了一个新的导航。比如,在等待导航守卫的过程中又调用了 router.push
。duplicated
:导航被阻止,因为我们已经在目标位置了。// 正在尝试从主页面访问 about 页面
router.push('/about').catch(failure => {
if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
failure.to.path // '/about'
failure.from.path // '/'
}
})