vue入门三-Vue Router

参考:丁丁的哔哩哔哩

vue router

路由注意点:

  1. js根据路径的变化显示不同的内容;
  2. 路由核心:改变url,但是页面不进行整体刷新。
  3. 路由表,是一个映射表,一个路由就是一组映射关系,key:value。key:表示路由,value:可以为function或者Component组件
<!-- vue-router是基于路由和组件的,路由是用来设定访问路径,将路径和组件映射起来,-->
import { createMemoryHistory, createRouter } from 'vue-router'
// 定义路由组件
import HomeView from './HomeView.vue'
import AboutView from './AboutView.vue'
// 定义路由表
const routes = [
  { path: '/', component: HomeView },
  { path: '/about', component: AboutView },
]
// 创建路由实例并传递"routes"配置
const router = createRouter({
  history: createMemoryHistory(),
  routes,
})
<template>
  <h1>Hello App!</h1>
  <p>
    <strong>Current route path:</strong> {{ $route.fullPath }}
  </p>
  <nav>
  	<!--通过传递 'to' 来指定链接-->
  	<!--<router-link> 将呈现一个带有正确"href"属性的<a>标签 -->
    <RouterLink to="/">Go to Home</RouterLink>
    <RouterLink to="/about">Go to About</RouterLink>
  </nav>
  <main>
    <RouterView />
  </main>
</template>

RouterLink
使用一个自定义组件 router-link 来创建链接。这使得 vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。
它的"to"属性指向路由,根据index配置的路由表,对应要展示的组件。

RouterView
路由出口,占位符。路由匹配到的组件将渲染在这里

带参数的动态路由匹配

路径参数:

import User from './User.vue'

// 这些都会传递给 `createRouter`
const routes = [
  // 动态字段以冒号开始
  { path: '/users/:id', component: User },
]

如何使用:

// 会映射到同一个路由
path = "/users/johnny"
path = "/users/jolyne"

组件user.vue:

import {useRoute} from "vue-router";
// 获取当前活跃的路由对象的路径参数,可以将路径参数传入接口用于获取数据
console.log(useRoute().params.id)

404页面

404页面,匹配上述路径外的所有路径

const routes = [
    {   path: '/',
        component: HomeView
    },
    {   path: '/about',
        component: AboutView
    },
    {   path: '/user/:id',
        component: UserView
    },
    {   path: '/:path(.*)',// 正则表达式,匹配上述路径外的所有路径
        component: () => import('@/views/404.vue')
    }
]

动态路由参数的正则限制

  1. 动态路由的参数一定是数字, /news/456
  {  path: '/news/:id(\\d+)',
        component: () => import('@/views/news.vue')
  },
  1. 有多个参数, /news/456/789/kkk
  {  path: '/news/:id+',
        component: () => import('@/views/news.vue')
  },
  1. 参数可有可无 ,参数不可以重复叠加, /news/456/789 或者 /news
{  path: '/news/:id*',
        component: () => import('@/views/news.vue')
  },
  1. 参数可有可无,但是参数不可以重复叠加
{  path: '/news/:id?',
        component: () => import('@/views/news.vue')
  },

嵌套路由

<!-- App.vue -->
<template>
  <router-view />
</template>

<!-- User.vue -->
<template>
  <div class="user">
    <h2>User {{ $route.params.id }}</h2>
    <router-view />
  </div>
</template>

<!-- index.ts -->
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {
        // 当 /user/:id/profile 匹配成功
        // UserProfile 将被渲染到 User 的 <router-view> 内部
        path: 'profile',
        component: UserProfile,
      },
      {
        // 当 /user/:id/posts 匹配成功
        // UserPosts 将被渲染到 User 的 <router-view> 内部
        path: 'posts',
        component: UserPosts,
      },
    ],
  },
]

编程式导航

  1. 声明式:<router-link :to="...">
  2. 编程式:router.push(...)
// 字符串路径
router.push('/users/eduardo')

// 带有路径的对象
router.push({ path: '/users/eduardo' })

// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })

// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })

替换当前位置
在导航时不会向 history 添加新记录,而是替换原先页面;浏览器左上方的前进、后退按钮失效

  1. 声明式:
<router-link :to="..." replace>
  1. 编程式:
router.push({ path: '/home', replace: true })
// 相当于
router.replace({ path: '/home' })

横跨历史

// 向前移动一条记录,与 router.forward() 相同
router.go(1)

// 返回一条记录,与 router.back() 相同
router.go(-1)

// 前进 3 条记录
router.go(3)

// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)

命名路由: 给路由起个名字,name属性

const routes = [
  {
    path: '/user/:username',
    name: 'profile', 
    component: User
  }
]

<router-link :to="{ name: 'profile', params: { username: 'erina' } }">
  User profile
</router-link>

命名视图: 访问一个路径,同时 (同级) 展示多个视图

<router-view name="LeftSidebar" />
<router-view />
<router-view  name="RightSidebar" />

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      components: {
        default: Home,
        // LeftSidebar: LeftSidebar 的缩写
        LeftSidebar,
        // 它们与 `<router-view>` 上的 `name` 属性匹配
        RightSidebar,
      },
    },
  ],
})

重定向

  1. 一般形式:
const routes = [
	{ 
		path: '/home', redirect: '/' 
	}
]
  1. 重定向的目标也可以是一个命名的路由:
const routes = [
	{ 
		path: '/home', redirect: { name: 'homepage' }
	 }
]
  1. 一个方法
const routes = [
  {
    // /search/screens -> /search?q=screens
    path: '/search/:searchText',
    redirect: to => {
      // 方法接收目标路由作为参数
      // return 重定向的字符串路径/路径对象
      return { path: '/search', query: { q: to.params.searchText } }
    },
  },
  {
    path: '/search',
    // ...
  },
]

别名 alias

将 / 别名为 /home,意味着当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /。

const routes = [
	{ 
		path: '/',
		alias: '/home',
		component: Homepage
	}
]

多个别名:数组形式

const routes = [
  {
    path: '/users',
    component: UsersLayout,
    children: [
      // 为这 3 个 URL 呈现 UserList
      // - /users
      // - /users/list
      // - /people
      { path: '', component: UserList, alias: ['/people', 'list'] },
    ],
  },
]

将 props 传递给路由组件

之前的示例:
使用$route.params获取路径参数

<!-- User.vue -->
<template>
  <div>
    User {{ $route.params.id }}
  </div>
</template>

现在的示例:
通过声明 prop 来删除对 $route 的直接依赖:

const routes = [
  { 
  	path: '/user/:id', 
  	component: User, 
  	props: true 
  }
]

使用defineProps来声明id属性

<!-- User.vue -->
<script setup>
defineProps({
  id: String
})
</script>

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

命名视图
对于有命名视图的路由,你必须为每个命名视图定义 props 配置:

const routes = [
  {
    path: '/user/:id',
    components: { default: User, sidebar: Sidebar },
    props: { default: true, sidebar: false }
  }
]

在User.vue中可以使用defineProps获取id;而在Sidebar.vue使用defineProps获取不到id

不同的历史模式

  1. Hash 模式
  2. HTML5 模式

两者区别:一个有“#”号,一个没有

导航守卫

全局前置守卫

const router = createRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
  // 返回 false 以取消导航
  // return false
  next() // 放行
})

每路守卫(路由独享的守卫)

const routes = [
  {
    path: '/users/:id',
    component: UserDetails,
    beforeEnter: (to, from) => {
      // reject the navigation
      return false
    },
  },
]

组件内部类似生命周期函数的守卫

<script>
export default {
  beforeRouteEnter(to, from) {
    // 在渲染该组件的对应路由被验证前调用
    // 不能获取组件实例 `this` !
    // 因为当守卫执行时,组件实例还没被创建!
  },
  beforeRouteUpdate(to, from) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 `/users/:id`,在 `/users/1` 和 `/users/2` 之间跳转的时候,
    // 由于会渲染同样的 `UserDetails` 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 因为在这种情况发生的时候,组件已经挂载好了,导航守卫可以访问组件实例 `this`
  },
  beforeRouteLeave(to, from) {
    // 在导航离开渲染该组件的对应路由时调用,通常用来预防用户在还未保存修改前突然离开
    // 与 `beforeRouteUpdate` 一样,它可以访问组件实例 `this`
  },
}
</script>

beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。

但可以通过传一个回调给 next 来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数:

const age = 18;

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例 
    // 例如 vm.age
  })
}

路由懒加载

静态导入:全部导入
路由懒加载:用到时再加载

// 将
// import UserDetails from './views/UserDetails.vue'
// 替换成
// const UserDetails = () => import('./views/UserDetails.vue')

const router = createRouter({
  // ...
  routes: [
    { path: '/users/:id', component: () => import('./views/UserDetails.vue') },
  ],
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值