Vue —— 精讲 VueRouter( 2 )

接着上一讲的内容

八、编程导航中的路由传参

这里我们有这样的方式去传递路由参数
我们可以通过$touter.query的方式获取传递过来的参数,
我们不需要,在路由里面加:id,什么的去获取这个东西,我们可以特殊的方式传递数据,就好了

  1. 传递
    /App.vue
<router-linnk :to="{path:'/profuke',query:{name:'why','age':18}}"></router-linnk>

  1. 获取
    /Profile.vue
//通过这样的方式就能把传递过来的query全部搞到手
<h2> {{ $route.query }} </h2>
  1. 注意这里如何通过方法传递?非常的简单
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. 解决方案1

我们都知道,我们的组件有生命周期函数,其中最重要的生命周期函数是如下的四个

  • created()
  • mounted()
  • updated()

那么我们可以在组件创建的时候,在页面还没有挂载上dom上之前,creatd生命周期里改它的title,就能实现我们的需求
/Home.vue

created(){
    doucument.title='首页'
}
  1. 优化解决方案

我们确实实现了这样的一个需求,但是有问题,如果有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

知识点补充

  1. 在vue的官网实际上有这个解释和说明,只需要在router-view的地方包一个东西就好了,
<keep-alive>
    <router-view/>
</keep-alive>

这样就可以把原来的东西组件的一些状态 缓存起来。缓存起来之后,下一次切换的时候就不会重新去创建路由

keep-alive是vue内置的一个组件,可以使被包含的组件保存状态,避免重新的渲染,提高性能

  1. 几个常见的生命周期

注意啊,这个东西一定要配合几个生命钩子函数一起使用,要不然就显得蛋疼
下面的几个生命周期是我们经常使用的东西

// 组件销毁调用的几个方法
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管理,那么怎么做呢?

  1. 要实现这样的功能要调用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
            }
        },
    }
  1. 使用keep-alive特有的属性来实现这样的功能
    /App.vue
<keep-alive exclude="User,About">
  <router-view/>
</keep-alive>

<!-- 实际上,我们还有include,不必多说,这个是包含的意思 -->

给路径起别名

实际上的别名都是在weboack配置好的

  1. 我们先来看看vue中的@是搞什么的

实际上非常的简单 这个@符号就是代表当前的这个src文件夹根目录

  1. 我们来搞搞吧在vue2.0的版本中,我们是可以配置的,
    /build/webpack.base.config.js

 resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': resolve('src'), // 这里的@就是一个队src文件夹的映射
    }
  },

上一篇:如何利用python实现生命游戏


下一篇:Java引用类型之软引用(1)