接着上一讲的内容
八、编程导航中的路由传参
这里我们有这样的方式去传递路由参数
我们可以通过$touter.query的方式获取传递过来的参数,
我们不需要,在路由里面加:id,什么的去获取这个东西,我们可以特殊的方式传递数据,就好了
- 传递
/App.vue
<router-linnk :to="{path:'/profuke',query:{name:'why','age':18}}"></router-linnk>
- 获取
/Profile.vue
//通过这样的方式就能把传递过来的query全部搞到手
<h2> {{ $route.query }} </h2>
- 注意这里如何通过方法传递?非常的简单
profileClick(){
this.$router.push({
path:'/profile',
query:{
name:'kebo',
age:19,
heigth:1.87
}
})
}
九、 $router 和 $route的区别
\(router是值的是new Router()的对象,\)route 是当前处于活跃状态的 路由对象,比如你当前的在home下那么$route就是当前的具体状态的路由对象
源码解析,我们看看vue.use()这个方法到底做了什么
// 实际上,我们的按照插件的时候,不管是什么插件,实际上user的时候是去执行它对应的install方法
export declare class VueRouter {
constructor(options?: RouterOptions)
app: Vue
mode: RouterMode
currentRoute: Route
beforeEach(guard: NavigationGuard): Function
beforeResolve(guard: NavigationGuard): Function
afterEach(hook: (to: Route, from: Route) => any): Function
push(location: RawLocation): Promise<Route>
replace(location: RawLocation): Promise<Route>
push(
location: RawLocation,
onComplete?: Function,
onAbort?: ErrorHandler
): void
replace(
location: RawLocation,
onComplete?: Function,
onAbort?: ErrorHandler
): void
go(n: number): void
back(): void
forward(): void
getMatchedComponents(to?: RawLocation | Route): Component[]
onReady(cb: Function, errorCb?: ErrorHandler): void
one rror(cb: ErrorHandler): void
addRoutes(routes: RouteConfig[]): void
resolve(
to: RawLocation,
current?: Route,
append?: boolean
): {
location: Location
route: Route
href: string
// backwards compat
normalizedTo: Location
resolved: Route
}
static install: PluginFunction<never>
}
// 我们在vue-router源码中,看到了一个install方法,这个就是use中执行的方法,
// 源码中最重要的还有一个方法,现在,我们先看看就好,后面会说到
export interface RouterOptions {
routes?: RouteConfig[]
mode?: RouterMode
fallback?: boolean
base?: string
linkActiveClass?: string
linkExactActiveClass?: string
parseQuery?: (query: string) => Object
stringifyQuery?: (query: Object) => string
scrollBehavior?: (
to: Route,
from: Route,
savedPosition: Position | void
) => PositionResult | Promise<PositionResult> | undefined | null
}
实际上,在vue的设计中,很多地方都用到了一些高级的JS知识,比如get() set()方法等... 这些知识点都在<<js高级程序设计>>中可以获取,所以高程吃透80%什么框架都是soeasy
十、导航守卫
阅读源码非常的重要,我们有很多的东西实际上都可以不用详细的去记,只需要看源码理解就好了。
需求1实现页面的title
我们有这样的一个需求,我们希望我们页面的title会跟着我们的组件发生变化,是home就显示首页,是about就显示关于
- 解决方案1
我们都知道,我们的组件有生命周期函数,其中最重要的生命周期函数是如下的四个
- created()
- mounted()
- updated()
那么我们可以在组件创建的时候,在页面还没有挂载上dom上之前,creatd生命周期里改它的title,就能实现我们的需求
/Home.vue
created(){
doucument.title='首页'
}
- 优化解决方案
我们确实实现了这样的一个需求,但是有问题,如果有100k组件,我们不太可能写100k同样的代码,我们选择使用路由导航
在Router源码中,有这样的一个东西
export type NavigationGuard < V extends Vue = Vue > = (
to: Route,//通过源码,我们知道这个to实际上就是当前页面的那个route对象
from: Route,//这个from就是指的是父级路由 route 对象
next: (to?: RawLocation | false | ((vm: V) => any) | void) => void
) => any
export declare class VueRouter {
constructor(options?: RouterOptions)
app: Vue
mode: RouterMode
currentRoute: Route
beforeEach(guard: NavigationGuard): Function
beforeResolve(guard: NavigationGuard): Function
afterEach(hook: (to: Route, from: Route) => any): F
于是我们就能在beforeEach的时候拦截一下做一些特殊的处理
需要注意的是:如果是多个嵌套路由,就需要 to.matched[0].meta.title,同样的,这个也适用于非嵌套路由,为了统一代码规范,我们都加上这个meta比较好
/router/idnex.js
path: '/home',
component: Home,
meta: {
title: '首页'
},
children: [{
path: '',
redirect: 'news'
},
{
path: 'news',
component: HomeNews,
meta: {
title: '新闻'
}
},
{
path: 'message',
component: HomeMessage,
meta: {
title: '消息'
}
},
]
},
{
path: '/about',
component: About
},
{
path: "/user/:usermsg",
component: User
}
]
const router = new Router({
routes,
mode: "history"
})
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title
next()
})
我们的路由hook还有很多
我们的路由还有很多的hook钩子,请去翻阅官方的文档
十一、keep-alive
我们现在有这样的一个需求,我们希望我们跳转的时候把状态保持下来(换句话说就是缓存起来),要实现这样的一个功能,我们就需要使用到keep-alive
知识点补充
- 在vue的官网实际上有这个解释和说明,只需要在router-view的地方包一个东西就好了,
<keep-alive>
<router-view/>
</keep-alive>
这样就可以把原来的东西组件的一些状态 缓存起来。缓存起来之后,下一次切换的时候就不会重新去创建路由
keep-alive是vue内置的一个组件,可以使被包含的组件保存状态,避免重新的渲染,提高性能
- 几个常见的生命周期
注意啊,这个东西一定要配合几个生命钩子函数一起使用,要不然就显得蛋疼
下面的几个生命周期是我们经常使用的东西
// 组件销毁调用的几个方法
destroy(){}
destroyed(){}
// > 下面的 活跃 状态的方法 仅仅在有keep-alive包裹的router-view下才有用
activated(){}
deactivated(){}
案例实现具体代码
这里我们需要面临的是这样的一个需求,实际上 单纯的看keep-alive的东西,还是非常简单的,但是由于是嵌套路由以及重定向就需要考虑,它的路由地址会影响整个keep-alive。所以会出现一定的问题
如下是解决方案,这里面使用的路由的一些hook函数,还是使用了keep-alive的hook函数
- 去除路由的默认跳转行为,要不然它会干扰我们的keep-alive的状态保持
/route/index.js
const routes = [{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: Home,
meta: {
title: '首页'
},
children: [{
// 这里去除了 路由的重定向,避免造成干扰
path: 'news',
component: HomeNews,
},
{
path: 'message',
component: HomeMessage,
},
]
},
{
path: '/about',
component: About,
meta: {
title: '关于'
}
},
{
path: "/user/:usermsg",
component: User,
meta: {
title: '用户'
}
}
]
- keep-alive管理路由
/App.vue
<keep-alive>
<router-view/>
</keep-alive>
- 去我们的需要保持的子路由页面中动一下手脚
/home.vue
<template>
<div>
<h2>我是首页</h2>
<p>我是首页内容哈哈哈</p>
<router-link to="/home/news">news</router-link>
<router-link to="/home/message">message</router-link>
<router-view/>
</div>
</template>
<script>
export default {
data() {
return {
path: '/home/news'
}
},
created () {
console.log('created');;
},
// kepp-alive当前管理状态活跃时就去跳转到指定路由地址
activated(){
this.$router.push(this.path)
},
// 离开的时候保存这个路由地址,下一次活跃的时候重新赋值上就好了
beforeRouteLeave(to, from, next) {
console.log(this.$route.path);
this.path = this.$route.path
next();
},
}
</script>
<style scoped>
</style>
新的需求
我们现在又有新的需求了,要知道一点,我们目前的所有的组件都是被保持状态的,现在我们有这样的一个需求,我们希望User组件还有About组件可以不被keep-alive管理,那么怎么做呢?
- 要实现这样的功能要调用keep-alive的属性,但是这个属性依赖于组件的名字,所以你的组件要有name属性,现在我们就去给user还有profile组件加上这个name属性
export default {
computed: {
name:'User',
username() {
return this.$route.params.usermsg
}
},
}
=======
export default {
computed: {
name:'About',
username() {
return this.$route.params.usermsg
}
},
}
- 使用keep-alive特有的属性来实现这样的功能
/App.vue
<keep-alive exclude="User,About">
<router-view/>
</keep-alive>
<!-- 实际上,我们还有include,不必多说,这个是包含的意思 -->
给路径起别名
实际上的别名都是在weboack配置好的
- 我们先来看看vue中的@是搞什么的
实际上非常的简单 这个@符号就是代表当前的这个src文件夹根目录
- 我们来搞搞吧在vue2.0的版本中,我们是可以配置的,
/build/webpack.base.config.js
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'), // 这里的@就是一个队src文件夹的映射
}
},