Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue-Router简单使用 #12

Open
LyzSg opened this issue Feb 2, 2019 · 0 comments
Open

Vue-Router简单使用 #12

LyzSg opened this issue Feb 2, 2019 · 0 comments
Labels

Comments

@LyzSg
Copy link
Owner

LyzSg commented Feb 2, 2019

1. 开始

通过<router-link>导航,默认渲染为a标签,但不会像a标签那样点几次就跳转几次,如果是同一页面,则不进行跳转。

通过tag特性可以修改默认渲染的标签。

如果路由匹配,则会自动添加类名.router-link-active(注意/about会匹配到/)。如果路由被选中,则会自动添加类名.router-link-exact-active。类名可配置。

<router-link to="/">Home</router-link>

<!-- 渲染为li标签 -->
<router-link tag="li" to="/">Home</router-link>

路由出口<router-view>,匹配到的组件都会渲染到这里。

<router-view></router-view>

引入vue和vue-router,通过Vue.use使用vue-router,创建router实例并注入。

import Vue from 'vue'
import VueRouter from 'vue-router' // 同Vue一样是个构造函数

import App from './App.vue'
import Home from './views/Home' // 自动找到.vue文件

Vue.use(VueRouter) // 插件安装

const router = new VueRouter({ // 创建router实例,配置routes
  // linkActiveClass: 'active', 
  // linkExactActiveClass: 'exact',
  routes: [
    { 
      path: '/', 
      component: Home 
      alias: '/home'   // 别名,当访问/home时显示的是/
    },
    { 
      path: '/about', 
      component: () => import('./views/About.vue') // 懒加载 
    },
    {
      path: '/a',
      component: A,
      redirect: '/b' // 重定向
      // redirect: {name: 'b'}
      // redirect: to => {  
        // 方法接收 目标路由 作为参数
        // return 重定向的 字符串路径/路径对象
      }
    }
  ],
  mode: 'hash'
})

new Vue({
  router, // 注入
  render: h => h(App)
}).$mount('#app')

之后,在任何组件内部即可使用 $router访问router实例,使用 $route访问当前路由。

默认路由方式为Hash路由,可在路由配置中通过mode改成history

2. 动态路由

动态路径参数: 一个路径参数用冒号:标记

const router = new VueRouter({
  routes: [
    // 动态路径参数 id 和 post_id
    { path: '/user/:id/post/:post_id', component: User }
  ]
})

当匹配到一个路由时,参数值会设置到$route.params里。例如/user/123/post/456$route.params = { id: 123, post_id: 456 }

path匹配使用的是path-to-regexp引擎

组件复用: 当从/user/123跳转到/user/321时,User组件会被复用,所以组件的生命周期钩子不会再被调用

但是每次路由更新,$route都是一个新的对象,所以可以侦听$route来探测路由变化。

watch: {
  $route(val, oldVal) {
    // ...
  }
}

3. 嵌套路由

在路由组件中同样可以使用<router-view>先渲染子路由。

有时在to里直接写路径不方便,此时可以给使用命名路由,配置路由的时候给一个name,之后给to传如一个配置对象即可。

<template>
  <div class="user">
    User
    <!-- <router-link to="/user/123/post/456"></router-link> -->
    <router-link :to="{name: post, params: { post_id: 456 }}">post</router-link>
    <router-view></router-view>
  </div>
</template>

配置routes时,children跟routes同样是个数组,用来配置子路由。path默认在父级路由的路径下,如果以/开头则在根目录下。

const router = new VueRouter({
  routes: [
    {
      path: '/user/:id',
      component: User,
      children: [
        {
          // 匹配 /user/123/post/456
          path: 'post/:post_id',
          name: 'post',
          component: UserPost
        }
      ]
    }
  ]
})

4. 命名视图

有时候想要一个页面用多个视图<router-view>,于是可以给它个name,并在配置路由的时候,使用components替换component来设置多个组件

<router-view></router-view>
<router-view name="a"></router-view>
<router-view name="b"></router-view>
const router = new VueRouter({
  routes: [
    path: '/',
    components: {
      default: Home, 
      a: Bar,
      b: Baz
    }
  ]
})

5. 编程式导航

除了使用声明式的<router-link>来定义导航,还可以利用router实例方法来实现。

  • $router.push(location, onComplete?, onAbort?)
    等同于<router-link :to="location">,同样可以传一个路由字符串或者配置对象

  • $router.replace(location, onComplete?, onAbort?)

  • $router.go(n) 向前或者向后多少步

这些方法都是效仿window.historyAPI的。

6. 利用prop给路由组件传参

在组件中使用$route会使得路由与该组件高度耦合,限制灵活性。

在配置路由时,设置props属性为true,则route.params将会被设置为组件属性。

const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'
}
const router = new VueRouter({
  routes: [
    {
      path: 'user',
      component: User,
      props: true
    },
    // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项:
    {
      path: '/user/:id',
      components: { default: User, sidebar: Sidebar },
      props: { default: true, sidebar: false }
    }
  ]
})

props也可以是一个对象,对象键值将原样传给组件属性。

props也可以是一个函数,函数参数是目标路由,需要返回props作为组件属性。

const router = new VueRouter({
  routes: [
    { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
  ]
})

7. 导航守卫

全局守卫: beforeEach、afterEach

const router = new VueRouter({ ... })

// to from 都是路由对象,next()允许跳转 ,next(false)阻止跳转
router.beforeEach((to, from, next) => {
  // ...
  if(...) {
    next()
  } else {
    next(false)
  }
})

// 没有next
router.afterEach((to, from) => {
  // ...
})

路由独享守卫: beforeEnter

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

组件内守卫: beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave

const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建

    // 唯一一个支持传递回调的守卫
    next(vm => {
      // 通过vm访问组件实例
    })
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

8. 路由元信息

定义路由时可配置meta字段。

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: {
        requiresAuth: true
      }
      children: [
        { path: 'bar', component: Bar }   
      ]
    }
  ]
})

routes配置中每个路由对象称为路由记录。当一个路由匹配成功时,它和它的子路由记录都会暴露在$route对象的$route.matched数组中。

因此,在有meta字段的路由中或者其所有子路由中可以遍历$route.matched来找到记录中的meta字段。

@LyzSg LyzSg added the Vue label Feb 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant