# 基础使用

# 安装

npm install vue-router

# 配置

  1. 执行插件

    // router/index.js
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    

    插件原理参见文章:插件源码分析

  2. 创建实例

    // router/index.js
    import VueRouter from 'vue-router'
    
    const routes = [
      {
        path: '/home',
        component: Home
      }
    ]
    
    const router = new VueRouter({
      mode: 'history',
      base: process.env.BASE_URL,
      routes
    })
    
    export default router
    

    全部路由配置参见:路由配置选项

  3. 绑定根实例

    // main.js
    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    
    new Vue({
      router,
      render: (h) => h(App)
    }).$mount('#app')
    

# 路由组件

<p>
  <router-link to="/home">home1</router-link> 
  <router-link :to="{name: 'home'}">home2</router-link>
  <router-link to="/home" replace>home3</router-link>
</p>
<router-view></router-view>
  1. router-link被渲染为a标签
  2. router-view用于容纳匹配到的组件
  3. to属性可以传入路径字符串,也可以传入location对象
  4. 使用replace替换掉当前history记录,而不是新增一条记录

# 导航方法

# router.push

router.push(location, onComplete?, obAbort?)
  • router-link组件内部调用该方法

  • 该方法会在history栈添加一条新纪录

  • location可以是一个字符串路径,也可以是一个描述地址的对象

    router.push('/home')
    router.push({path: '/home'})
    // /home/1
    router.push({name: 'home', params: {id: 1}})
    // /home?id=1
    router.push({path: '/home', query: {id: 1}})
    
  • onComplete: 导航成功后回调

  • onAbort: 导航终止后回调

# router.replace

router.replace(location, onComplete?, obAbort?)
  • 同router.push,只是不向history栈中添加记录、
  • router-link组件中添加replace属性则调用该方法

# router.go

router.go(n)
  • 在浏览器history记录中进行跳转
  • router.go(-1):后退一步
  • router.go(3): 前进三步
  • 如果n超过了history记录数量则不会执行

# 嵌套路由

// App.vue
<template>
	<div>
    <router-link to="/user/profile"></router-link>
    <!-- 根组件 -->
    <router-view></router-view>
  </div>
</template>

// User.vue
<template>
  <div>
    User
    <!-- 路由组件User -->
  	<router-view></router-view>
  </div>
</template>

// UserProfile.vue
<template>
	<div>
    <!-- 路由组件UserProfile -->
    UserProfile
  </div>
</template>
// router/index.js

const routes = [
  {
    path: '/uesr',
    component: User,
    children: [
      {
        path: 'profile', // 如果变成/profile则变为绝对路径,只能通过http://xxx/profile访问
        component: UserProfile
      }
    ]
  }
]
  • 如果被渲染的组件内还有router-view则可以使用嵌套路由。
  • 嵌套路由不同于路由组,不是简单的将一组路由归于一个BaseUrl之下,嵌套路由中的层级关系必须对应于组件中router-view的层级关系。比如User组件只能投射到App组件的router-view,而UserProfile只能投射到User组件的router-view。

# 动态路由

# 路径参数

const routes = [
  {
    path: '/user/:id',
    component: User
  }
]
  • 路径参数用:标记,参数值会被放到this.$route.params
  • 导航时使用/user/1{name: 'user', params: {id: 1}}作为参数

# 通配路由

  1. 使用通配符*匹配任意路径

    const routes = [
      {
        path: '/user-*',
        component: NotFound
      }
    ]
    
    • 通配符匹配的内容会传入this.$route.params.pathMatch字段
    • 导航时可以使用/user-123{name: 'user', params: {pathMatch: 123}}作为参数

# 命名路由和视图

# 命名路由

const routes = [
  {
    path: '/user',
    name: 'user',
    component: User
  }
]
  • 命名路由可以帮助开发者通过路由名实现导航,如router.push({name: 'user'})

# 命名视图

<template>
	<div>
    <router-link to="/home"></router-link>
    
    <router-view></router-view>
    <router-view name="sidebar"></router-view>
  </div>
</template>
const routes = [
  {
    path: '/home',
    components: {
      default: Main,
      sidebar: SideBar
    }
  }
]
  • router-view可以有多个,多个router-view之间通过命名加以区分
  • 如果没有name属性,则默认名为default

# 重定向和别名

# 重定向

const routes = [
  {
    path: '/profile',
    redirect: '/user/profile'
    // redirect: {name: 'userProfile'}
    // redirect: to => '/user' + to.path
  }
]
  • 重定向会将路由导航至新的地址,可以传入一个path,一个location对象,也可以传入函数
  • 如果传入函数,函数中的to指向的是当前路由,不是调转后的目标路由,这里to.path 为 /profile
  • 导航守卫不会作用在跳转路由上,而是作用在目标路由上,这里只会作用在/user/profile之上

# 别名

const routes = [
  {
    path: '/user',
    name: 'user',
    component: User,
    children: [
      {
        path: 'profile',
        name: 'userProfile',
        component: UserProfile,
        // 实际访问/user/profile
        alias: '/userprofile',
      },
    ],
  },
]
  • 别名用于路径重写,浏览器地址栏中会保留别名路径,包括this.$route对象中的路径也是别名
  • 别名可用于自定义路径,不必拘束于嵌套关系

# 组件传参

通常在组件内获取路由参数需要通过this.$route.params等方式,这样使得组件和route对象强耦合。

vue-router支持向组件props传参,避免组件自己从route对象中获取。

<template>
	<div>
    User {{ name }}
  </div>
</template>

<script>
export default {
  props: {
    name: String
  }
}
</script>
const routes = [
  {
    path: '/user/:name',
    component: User,
    props: true // 默认将this.$route.params传递给props
    // props: {name: 'zhuli'} // 静态传入
    // props: route => ({name: route.query.name})
  }
]

# 导航模式

# hash模式

vue-router默认使用hash模式:

http://localhost:8080/#/about/2

在hash模式下,前端路由被统一放在一个#后面,如此浏览器便不会重新发起请求

# history模式

hash模式不太好看,可以选择history模式:

const router = new VueRouter({
  mode: 'history',
  routes
})

history模式下的路径就和普通路径一样了:

http://localhost:8080/about/2

vue-router使用history.pushState方法更新history记录而不重新发起请求

但如果我们首次打开页面或者刷新页面,浏览器就会发起请求,不同于hash模式#前面的路径永远不变,history模式下的路径会整个传给后端服务器,比如nginx中配置:

location ^~ / {
  root /usr/share/html;
	index index.html;
}

那么当我们请求/home/user等路径时便会返回404,因为nginx下没有这个页面。(nginx会将路径名转换为文件路径进行文件查找)

所以为了防止这种404的情况,我们需要修改nginx的配置

location ^~ / {
	root /usr/share/nginx/html;
  try_files $uri $uri/ /index.html;
}

在这种配置下,所有的路径都会优先去找相应的文件(比如各种css,js文件),如果没找到就会重定向到http://localhost:8000/index.html地址,于是就可以解决上述的404问题。

#

上次更新: 2/13/2025, 3:29:47 AM