草庐IT

vue3+ts+vite 路由详解

微光无限 2023-11-11 原文

 安装

1.首先创建项目

npm init vite@latest

 输入文件名,选择Vue、TypeScript


2.vscode打开项目,安装router,less,less-loader,@types/node

npm i vue-router -S
npm i less less-loader -S
npm i @types/node -D
npm install pinia
npm install animate.css --save

*注意 Vue3中router要安装4版本,3版本的router语法和4不一样。

3.在components中创建login.vue和register.vue文件

<template>
  <div>我是注册组件</div>
</template>

<script setup lang="ts"></script>

<style scoped></style>

4.在src下创建router文件夹,创建index.ts文件

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: () => import("../components/login.vue"),
  },
  {
    path: "/register",
    component: () => import("../components/register.vue"),
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;

5.在main.ts中引入并注册router

import { createApp } from "vue";
import App from "./App.vue";
// 引入router
import router from "./router";
// .ues(router) 注册router
createApp(App).use(router).mount("#app");

6.在app.vue中写路由出口才能显示路由页面

<template>
  <!-- 切换路由 -->
  <router-link to="/">注册</router-link>
  <router-link to="/register">登录</router-link>
  <!-- 路由出口 -->
  <router-view></router-view>
</template>

<script setup lang="ts"></script>

<style scoped></style>

 

 路由模式

 

 命名路由

1.将router下index.ts文件里的路由命名

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    // 命名
    name: "Login",
    component: () => import("../components/login.vue"),
  },
  {
    path: "/register",
    // 命名
    name: "Register",
    component: () => import("../components/register.vue"),
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;

2.app.vue中使用

<template>
  <!-- 切换路由 -->
  <router-link :to="{ name: 'Login' }">注册</router-link>
  <router-link :to="{ name: 'Register' }">登录</router-link>
  <!-- 路由出口 -->
  <router-view></router-view>
</template>

<script setup lang="ts"></script>

<style scoped></style>

编程式导航

<template>
  <!--第一种方式 hash -->
  <!-- <button @click="toPage('/')">登录</button>
  <button @click="toPage('register')">注册</button> -->

  <!--第二种方式 命名 -->
  <button @click="toPage('Login')">登录</button>
  <button @click="toPage('Register')">注册</button>

  <!-- 路由出口 -->
  <router-view></router-view>
</template>

<script setup lang="ts">
// 引入useRouter
import { useRouter } from "vue-router";
// 使用router
const router = useRouter();
const toPage = (url: string) => {
  router.push({
    // hash形式
    // path: url,

    // 命名形式
    name: url,
  });
};
</script>

<style scoped></style>

路由传参

*注意下载 JSON to TS 插件,选中json文件(ctrl+shift+alt+s)可以转为ts文件

1.path,query传参

<template>
  <div>
    <ul v-for="item in data" :key="item.id">
      <li>{{ item.name }}</li>
      <li>{{ item.age }}</li>
      <button @click="toJson(item)">发送</button>
    </ul>
  </div>
</template>

<script setup lang="ts">
// 数据源
import { data } from "./list.json";
// 传数据的组件
import { useRouter } from "vue-router";

const router = useRouter();

// 定义类型
type Item = {
  name: string;
  age: number;
  id: number;
};
const toJson = (item: Item) => {
  router.push({
    path: "/",
    query: item,
  });
};
</script>

<style scoped></style>
<template>
  <div>{{ route.query.name }}</div>
  <div>{{ route.query.age }}</div>
</template>

<script setup lang="ts">
// 接收数据的组件
import { useRoute } from "vue-router";
const route = useRoute();
</script>

<style scoped></style>

2.name,params传参

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Father",
    component: () => import("../components/father.vue"),
  },
  {
    // 因为params传参是保存在内存中,所以接收参数的页面刷新会丢失数据
    // params传参需要配合动态路由参数一起使用就不会有上面的问题
    path: "/child/:id",
    name: "Child",
    component: () => import("../components/child.vue"),
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;
<template>
  <div>
    <ul v-for="item in data" :key="item.id">
      <li>{{ item.name }}</li>
      <li>{{ item.age }}</li>
      <button @click="toJson(item)">发送</button>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { data } from "./list.json";
import { useRouter } from "vue-router";
const router = useRouter();
type Item = {
  name: string;
  age: number;
  id: number;
};
const toJson = (item: Item) => {
  router.push({
    name: "Child",
    params: {
      id: item.id,
    },
  });
};
</script>

<style scoped></style>
<template>
  <div>{{ item?.name }}</div>
  <div>{{ item?.age }}</div>
  <div>{{ item?.id }}</div>
</template>

<script setup lang="ts">
import { data } from "./list.json";
import { useRoute } from "vue-router";
const route = useRoute();
// 接收参数
const item = data.find((v) => v.id === Number(route.params.id));
</script>

<style scoped></style>

嵌套路由

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    // 父路由
    path: "/user",
    component: () => import("../components/father.vue"),
    // 子路由
    children: [
      {
        path: "",
        component: () => import("../components/child1.vue"),
      },
      {
        path: "child2",
        component: () => import("../components/child2.vue"),
      },
    ],
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;
<template>
  <div>
    父路由
    <router-view></router-view>
    <router-link to="/user">child1</router-link>
    <router-link to="/user/child2">child2</router-link>
  </div>
</template>

<script setup lang="ts"></script>

<style scoped></style>

命名视图

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    components: {
      default: () => import("../components/layout/menu.vue"),
      header: () => import("../components/layout/header.vue"),
      content: () => import("../components/layout/content.vue"),
    },
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;
<script setup lang="ts"></script>

<template>
  <div>
    <router-view></router-view>
    <router-view name="header"></router-view>
    <router-view name="content"></router-view>
  </div>
</template>

<style scoped></style>

重定向/别名

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: () => import("../components/login.vue"),
    // 字符串形式重定向
    // redirect: "/menu",

    // 对象形式重定向
    // redirect: { path: "/menu" },

    // 函数形式重定向
    redirect(to) {
      return {
        path: "/content",
        query: to.query,
      };
    },
    alias: ["/root", "/lala"], // 设置别名(为重定向服务)
    children: [
      {
        path: "/menu",
        components: {
          default: () => import("../components/layout/menu.vue"),
        },
      },
      {
        path: "/content",
        components: {
          aaa: () => import("../components/layout/header.vue"),
          bbb: () => import("../components/layout/content.vue"),
        },
      },
    ],
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;

 配置别名

import { defineConfig } from "vite";
import { fileURLToPath, URL } from "url";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // 配置别名
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
});

注意:如果在vite.config.ts配置别名时,出现 找不到模块“xxx”或其相应的类型声明 这种报错时,需要安装 “@types/node” 模块,处理配置别名不生效的问题

npm i @types/node -D

导航守卫  

loadingBar.vue

<template>
  <div class="wraps">
    <div ref="bar" class="bar"></div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
let speed = ref<number>(1);
let bar = ref<HTMLElement>();
let timer = ref<number>(0);
const startLoading = () => {
  let dom = bar.value as HTMLElement;
  speed.value = 1;
  timer.value = window.requestAnimationFrame(function fn() {
    if (speed.value < 90) {
      speed.value += 1;
      dom.style.width = speed.value + "%";
      timer.value = window.requestAnimationFrame(fn);
    } else {
      speed.value = 1;
      window.cancelAnimationFrame(timer.value);
    }
  });
};

const endLoading = () => {
  let dom = bar.value as HTMLElement;
  setTimeout(() => {
    window.requestAnimationFrame(() => {
      speed.value = 100;
      dom.style.width = speed.value + "%";
    });
  }, 500);
};

defineExpose({
  startLoading,
  endLoading,
});
</script>

<style scoped lang="less">
.wraps {
  position: fixed;
  top: 0;
  width: 100%;
  height: 2px;
  .bar {
    height: inherit;
    width: 0;
    background: blue;
  }
}
</style>

 main.ts

import { createApp, createVNode, render } from "vue";
import App from "./App.vue";
import router from "./router";
import ElementUI from "element-plus";
import "element-plus/dist/index.css";
import loadingBar from "./components/loadingBar.vue";
const app = createApp(App);

app.use(router);
app.use(ElementUI);
app.mount("#app");

// 设置白名单(允许直接跳转的路由)
const whileList = ["/"];
// 设置前置守卫
router.beforeEach((to, from, next) => {
  if (whileList.includes(to.path) || localStorage.getItem("token")) {
    next();
    Vnode.component?.exposed?.startLoading();
  } else {
    next("/");
  }
});

const Vnode = createVNode(loadingBar);
render(Vnode, document.body);
console.log(Vnode);

// 设置后置守卫(一般用做导航完成的loading页面)
router.afterEach((to, from) => {
  Vnode.component?.exposed?.endLoading();
});
to: Route, 即将要进入的目标 路由对象;
from: Route,当前导航正要离开的路由;
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

路由元信息

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 定义路由元信息meta的title的类型
declare module "vue-router" {
  interface RouteMeta {
    title: string;
  }
}

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: () => import("@/views/login.vue"),
    // 设置路由元信息
    meta: {
      title: "登录页面",
    },
  },
  {
    path: "/register",
    component: () => import("@/views/register.vue"),
    // 设置路由元信息
    meta: {
      title: "注册页面",
    },
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import ElementUI from "element-plus";
import "element-plus/dist/index.css";
const app = createApp(App);

app.use(router);
app.use(ElementUI);
app.mount("#app");

// 设置白名单(允许直接跳转的路由)
const whileList = ["/"];
// 设置前置守卫
router.beforeEach((to, from, next) => {
  // 设置路由元信息
  document.title = to.meta.title;
  if (whileList.includes(to.path) || localStorage.getItem("token")) {
    next();
  } else {
    next("/");
  }
});

路由过度动效

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";

// 定义title的类型
declare module "vue-router" {
  interface RouteMeta {
    title: string;
    transition: string;
  }
}

// 路由类型:RouteRecordRaw
const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    component: () => import("@/views/login.vue"),
    // 设置路由元信息
    meta: {
      title: "登录页面",
      // 设置路由动效类名(基于animate动画库)
      transition: "animate__bounceIn",
    },
  },
  {
    path: "/register",
    component: () => import("@/views/register.vue"),
    // 设置路由元信息
    meta: {
      title: "注册页面",
      // 设置路由动效类名(基于animate动画库)
      transition: "animate__fadeInUpBig",
    },
  },
];

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,
});

export default router;

app.vue

<script setup lang="ts">
import "animate.css";
</script>

<template>
  <div>
    // 插槽
    <router-view #default="{ route, Component }">
      // 利用内置transition组件切换animate库类名来控制动画效果
      <transition
        :enter-active-class="`animate__animated ${route.meta.transition}`"
      >
        // 绑定相关路由组件
        <component :is="Component"></component>
      </transition>
    </router-view>
  </div>
</template>

<style scoped></style>

滚动行为

const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes,

  // 滚动行为
  scrollBehavior: (to, from, savePosition) => {
    if (savePosition) {
      return savePosition;
    } else {
      return {
        top: 500,
      };
    }
  },
});

动态路由


const initRouter = async () => {
    const result = await axios.get('http://localhost:9999/login', { params: formInline });
    result.data.route.forEach((v: any) => {
        router.addRoute({
            path: v.path,
            name: v.name,
                                    //这儿不能使用@
            component: () => import(`../views/${v.component}`)
        })
        router.push('/index')
    })
    console.log(router.getRoutes());
 
}

有关vue3+ts+vite 路由详解的更多相关文章

  1. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  2. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  3. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  4. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  5. ruby-on-rails - Rails - 从命名路由中提取 HTTP 动词 - 2

    Rails中有没有一种方法可以提取与路由关联的HTTP动词?例如,给定这样的路线:将“users”匹配到:“users#show”,通过:[:get,:post]我能实现这样的目标吗?users_path.respond_to?(:get)(显然#respond_to不是正确的方法)我最接近的是通过执行以下操作,但它似乎并不令人满意。Rails.application.routes.routes.named_routes["users"].constraints[:request_method]#=>/^GET$/对于上下文,我有一个设置cookie然后执行redirect_to:ba

  6. ruby-on-rails - 如何在 Rails 中设置路由的默认格式? - 2

    路由有如下代码:resources:orders,only:[:create],defaults:{format:'json'}resources:users,only:[:create,:update],defaults:{format:'json'}resources:delivery_types,only:[:index],defaults:{format:'json'}resources:time_corrections,only:[:index],defaults:{format:'json'}是否可以使用1个字符串为所有资源设置默认格式,每行不带“默认值”散列?谢谢。

  7. ruby - cucumber 的路由问题 - 2

    我正在使用rails3和cucumber,除了这个小问题,一切都很顺利GivenIamonthe"editautomobile"pageNoroutematches{:controller=>"automobiles",:action=>"edit"}(ActionController::RoutingError)现在路径在paths.rb中设置为edit_automobile_path在routes.rb中我有汽车作为资源,我搭建了它所以请告诉我我遗漏了什么,清楚地定义了路线并且匹配,因为我运行了rake路线并看到了路线。请指出正确的方向 最佳答案

  8. ruby - Rails 路由 : Giving default values for path helpers - 2

    有什么方法可以为url/path助手提供默认值吗?我有一个可选范围环绕我的所有路线:#config/routes.rbFoo::Application.routes.drawdoscope"(:current_brand)",:constraints=>{:current_brand=>/(foo)|(bar)/}do#...allotherroutesgohereendend我希望用户能够使用这些URL访问网站:/foo/some-place/bar/some-place/some-place为了方便起见,我在我的ApplicationController中设置了一个@current

  9. ruby-on-rails - 将 Rails 路由助手作为类方法添加到类中 - 2

    我如何将像“root_path”这样的Rails路由助手作为类方法添加到像my_model.rb这样的类中?所以我的课是这样的:ClassMyModeldefself.fooreturnself.root_pathendendMyModel.foo以上不起作用,因为ClassMyModel不响应root_path这是我所知道的:我可以使用includeRails.application.routes.url_helpers,但这只会将模块的方法添加为实例方法我试过扩展Rails.application.routes.url_helpers但它没用请随时给我上课:)

  10. ruby-on-rails - 获取 ActionController::RoutingError(当尝试使用 AngularJS 将数据发布到 Rails 服务器时,没有路由匹配 [OPTIONS] "/users" - 2

    尝试从我的AngularJS端将数据发布到Rails服务器时出现问题。服务器错误:ActionController::RoutingError(Noroutematches[OPTIONS]"/users"):actionpack(4.1.9)lib/action_dispatch/middleware/debug_exceptions.rb:21:in`call'actionpack(4.1.9)lib/action_dispatch/middleware/show_exceptions.rb:30:in`call'railties(4.1.9)lib/rails/rack/logg

随机推荐