vue3-router

220 阅读3分钟

零)路由定义&使用

// <router-view>是路由出口,点击路由/修改路由/修改url之后,由该标签渲染新视图


// ********** ./router文件 **********
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';

// 导入homepage相关固定路由
// const homepageModules = import.meta.globEager('./modules/**/home.ts');
// 导入modules非homepage相关固定路由
// const fixedModules = import.meta.globEager('./modules/**/!(home).ts');

// 存放固定的路由
const defaultRouterList: Array<RouteRecordRaw> = [
  {
    path: '/',
    redirect: '/device/query/index',
  },
  {
    path: '/403',
    name: '403Page',
    component: () => import('@/pages/result/403/index.vue'),
    meta: { title: '无权限' },
  },
  {
    path: '/500',
    name: '500Page',
    component: () => import('@/pages/result/500/index.vue'),
    meta: { title: '服务器出错页' },
    props: (route) => ({ query: route.query.msg }),
  },
  {
    path: '/404',
    name: '404Page',
    component: () => import('@/pages/result/404/index.vue'),
    meta: { title: '访问页面不存在页' },
    props: (route) => ({ query: route.query.msg }),
  },
  {
    path: '/:pathMatch(.*)',
    redirect: '/404',
  },
  {
    path: '/Login/:name',
    name: 'Login',
    component: () => import('@/pages/login/index.vue'),
  },
];

// 定义元信息类型
declare module 'vue-router' {
  interface RouteMeta {
    title: string;
  }
}

const router = createRouter({
  history: createWebHashHistory(),
  routes: defaultRouterList,
  scrollBehavior() {
    return {
      el: '#app',
      top: 0,
      behavior: 'smooth',
    };
  },
});

export default router;
// ********** main.ts文件 **********
import { createApp, Ref } from 'vue';
import router from './router';  // 前述路由定义
import './permission';          // 导航守卫
import App from './App.vue';

const app = createApp(App);

app.use(router);

app.mount('#app');

一)编程式导航

<script setup lang="ts">
import { useRouter } from 'vue-router';

// 编程式导航
const router = useRouter();

// 字符串
router.push('/');

// 对象
router.push({
  path: '/',
});

// 命名式
router.push({
  name: 'Login', // 路由定义时的name
});

</script>

二)不保留历史记录

不允许页面前进后退的方法

<template>
  <div style="border: 1px solid black; height: 500px; background-color: #3dc9b0">
  
    <!--   router-link使用replace属性-->
    <router-link replace to="/403">login</router-link>
    
    <hr />
    <t-button @click="click">click</t-button>
  </div>
</template>

<script setup lang="ts">
import { useRouter } from 'vue-router';
 const router = useRouter();
 
const click = () => {
  // 使用replace
  router.replace({ name: '500Page' });
};

</script>

<style scoped></style>

三)路由前进和后退

<script setup lang="ts">
import { useRouter } from 'vue-router';

// 编程式导航
const router = useRouter();

// 前进
const next = () => {
  router.go(1);
};

// 后退
const pre = () => {
  router.back();
};
</script>

四)路由传参

  • query方式,传递的参数会展示在url上
传递:
<script setup lang="ts">
import { useRouter } from 'vue-router';
// 编程式导航
const router = useRouter();
const click = () => {
  router.push({
    path: '/',     // 使用name也可以
    // 只能接收对象
    query: {
      name: 'menffy',
      age: 12,
    },
  });
};
</script>
// 使用
<script setup lang="ts">
import { useRoute } from 'vue-router';

const route = useRoute()
console.log(route.query.name);
console.log(route.query.age);

</script>
  • params方式,传递的参数不会展示到url,而是在内存里,页面刷新后数据会丢失
传递:
<script setup lang="ts">
import { useRouter } from 'vue-router';
// 编程式导航
const router = useRouter();
const click = () => {
  router.push({
    name: 'Login', 
    // 只能接收对象
    params: {
      name: 'menffy',
      age: 12,
    },
  });
};
</script>
// 使用
<script setup lang="ts">
import { useRoute } from 'vue-router';

const route = useRoute()
console.log(route.params.name);
console.log(route.params.age);

</script>

解决params刷新后值丢失问题

  • 动态路由参数
  • 动态路由参数只能接收一个,所以这里只演示传递一个name
{
  path: '/Login/:name',
  name: 'Login',
  component: () => import('@/pages/login/index.vue'),
},

五)命名视图

image.png

未命名的router-view,name默认是default image.png

六)嵌套路由 & 重定向 & 路由别名

路由定义

import Layout from '@/layouts/index.vue';

export default [
{
  path: '/device/apply',
  name: 'ApplyDevice',
  component: Layout,
  
  // 重定向
  // 方法一:
  // redirect: '/device/apply/task',
  
  // 方法二:
  // redirect: {
  //   path: '/device/apply/task',
  //   query: {
  //     name: 'menffy',
  //     age: 12,
  //   },
  // },
  
  // 方法三:
  redirect: (to) => {
    console.log('to ===>', to);
    return {
      path: '/device/apply/task',
      query: {
        name: 'menffy2',
        age: 12,
      },
    };
  },
  
  // 路由别名
  alias: ['/root', '/root2'],
  
  meta: { title: '设备申领', icon: 'cart' },
  
  // 嵌套路由
  children: [
    {
      path: 'task',
      name: 'ApplyDeviceTaskIndex',
      component: () => import('@/pages/apply-device/task/index.vue'),
      meta: {
        title: '主单管理',
      },
    },
  ],
},
]
正常访问

http://localhost:3002/#/device/apply

别名访问

以上3种访问方式效果一致

展示

自动重定向并添加后缀参数 image.png

七)导航守卫

小满文章

import { MessagePlugin } from 'tdesign-vue-next';
import NProgress from 'nprogress'; // progress bar
import 'nprogress/nprogress.css'; // progress bar style
import router from '@/router';

NProgress.configure({ showSpinner: false });

const whiteListRouters = ['/', '/login'];

// 前置守卫,路由跳转、前进、后退均会执行,可以做路由权限
router.beforeEach(async (to, from, next) => {
try {
  NProgress.start();
  
  //  **** 读取meta路由元信息 ****
  document.title = to.meta.title;
  
  if (whiteListRouters.includes(to.path)) {
    next();
    return;
  }
} catch (error) {
    await MessagePlugin.error(String(error));
    next('/500');
    NProgress.done();
  }
});

// 后置守卫
router.afterEach(() => {
  NProgress.done();
});

八)路由元信息

小满文章

见前文“导航守卫”的例子

九)路由过渡动效

小满Router(第十章-路由过渡动效)

十)滚动行为

小满Router(第十一章-滚动行为)

十一)动态路由

小满Router(第十二章-动态路由)